Merge "Address API review comments for Thermal API"
diff --git a/Android.bp b/Android.bp
index 4b22f9e..fb6ff0f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -352,12 +352,8 @@
         "core/java/android/service/chooser/IChooserTargetResult.aidl",
         "core/java/android/service/resolver/IResolverRankerService.aidl",
         "core/java/android/service/resolver/IResolverRankerResult.aidl",
-        "core/java/android/service/textclassifier/IConversationActionsCallback.aidl",
-        "core/java/android/service/textclassifier/ITextClassificationCallback.aidl",
+        "core/java/android/service/textclassifier/ITextClassifierCallback.aidl",
         "core/java/android/service/textclassifier/ITextClassifierService.aidl",
-        "core/java/android/service/textclassifier/ITextLanguageCallback.aidl",
-        "core/java/android/service/textclassifier/ITextLinksCallback.aidl",
-        "core/java/android/service/textclassifier/ITextSelectionCallback.aidl",
         "core/java/android/service/attention/IAttentionService.aidl",
         "core/java/android/service/attention/IAttentionCallback.aidl",
         "core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl",
@@ -1125,6 +1121,7 @@
         "core/java/android/os/HidlSupport.java",
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/Nullable.java",
         "core/java/android/annotation/SystemApi.java",
         "core/java/android/annotation/TestApi.java",
         "core/java/android/os/HwBinder.java",
@@ -1788,3 +1785,10 @@
     ],
 }
 
+// Creates an index of AIDL methods; used for adding UnsupportedAppUsage
+// annotations to private apis
+aidl_mapping {
+    name: "framework-aidl-mappings",
+    srcs: [":framework-defaults"],
+    output: "framework-aidl-mappings.txt"
+}
\ No newline at end of file
diff --git a/api/current.txt b/api/current.txt
index 9a6a911..395f5b2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -768,6 +768,7 @@
     field public static final int indicatorRight = 16843022; // 0x101010e
     field public static final int indicatorStart = 16843729; // 0x10103d1
     field public static final int inflatedId = 16842995; // 0x10100f3
+    field public static final int inheritShowWhenLocked = 16844194; // 0x10105a2
     field public static final int initOrder = 16842778; // 0x101001a
     field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
     field public static final int initialLayout = 16843345; // 0x1010251
@@ -3850,6 +3851,7 @@
     method public final void setFeatureDrawableUri(int, android.net.Uri);
     method public void setFinishOnTouchOutside(boolean);
     method public void setImmersive(boolean);
+    method public void setInheritShowWhenLocked(boolean);
     method public void setIntent(android.content.Intent);
     method public final void setMediaController(android.media.session.MediaController);
     method public void setPictureInPictureParams(@NonNull android.app.PictureInPictureParams);
@@ -4277,7 +4279,8 @@
     method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
     method public int unsafeCheckOp(String, int, String);
     method public int unsafeCheckOpNoThrow(String, int, String);
-    method public int unsafeCheckOpRaw(String, int, String);
+    method public int unsafeCheckOpRaw(@NonNull String, int, String);
+    method public int unsafeCheckOpRawNoThrow(@NonNull String, int, @NonNull String);
     field public static final int MODE_ALLOWED = 0; // 0x0
     field public static final int MODE_DEFAULT = 3; // 0x3
     field public static final int MODE_ERRORED = 2; // 0x2
@@ -4446,7 +4449,7 @@
 
   public final class AutomaticZenRule implements android.os.Parcelable {
     ctor @Deprecated public AutomaticZenRule(String, android.content.ComponentName, android.net.Uri, int, boolean);
-    ctor public AutomaticZenRule(String, android.content.ComponentName, android.content.ComponentName, android.net.Uri, android.service.notification.ZenPolicy, int, boolean);
+    ctor public AutomaticZenRule(@NonNull String, @Nullable android.content.ComponentName, @Nullable android.content.ComponentName, @NonNull android.net.Uri, @Nullable android.service.notification.ZenPolicy, int, boolean);
     ctor public AutomaticZenRule(android.os.Parcel);
     method public int describeContents();
     method public android.net.Uri getConditionId();
@@ -5263,6 +5266,7 @@
     method public String getGroup();
     method public int getGroupAlertBehavior();
     method public android.graphics.drawable.Icon getLargeIcon();
+    method @Nullable public android.content.LocusId getLocusId();
     method public CharSequence getSettingsText();
     method public String getShortcutId();
     method public android.graphics.drawable.Icon getSmallIcon();
@@ -5420,14 +5424,14 @@
     ctor @Deprecated public Notification.Action.Builder(int, CharSequence, android.app.PendingIntent);
     ctor public Notification.Action.Builder(android.graphics.drawable.Icon, CharSequence, android.app.PendingIntent);
     ctor public Notification.Action.Builder(android.app.Notification.Action);
-    method public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
-    method public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
-    method public android.app.Notification.Action build();
-    method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender);
+    method @NonNull public android.app.Notification.Action.Builder addExtras(android.os.Bundle);
+    method @NonNull public android.app.Notification.Action.Builder addRemoteInput(android.app.RemoteInput);
+    method @NonNull public android.app.Notification.Action build();
+    method @NonNull public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender);
     method public android.os.Bundle getExtras();
-    method public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean);
-    method public android.app.Notification.Action.Builder setContextual(boolean);
-    method public android.app.Notification.Action.Builder setSemanticAction(int);
+    method @NonNull public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean);
+    method @NonNull public android.app.Notification.Action.Builder setContextual(boolean);
+    method @NonNull public android.app.Notification.Action.Builder setSemanticAction(int);
   }
 
   public static interface Notification.Action.Extender {
@@ -5542,6 +5546,7 @@
     method @NonNull public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method @Deprecated public android.app.Notification.Builder setLights(@ColorInt int, int, int);
     method @NonNull public android.app.Notification.Builder setLocalOnly(boolean);
+    method @NonNull public android.app.Notification.Builder setLocusId(@Nullable android.content.LocusId);
     method @NonNull public android.app.Notification.Builder setNumber(int);
     method @NonNull public android.app.Notification.Builder setOngoing(boolean);
     method @NonNull public android.app.Notification.Builder setOnlyAlertOnce(boolean);
@@ -5807,7 +5812,6 @@
     method public java.util.List<android.app.NotificationChannel> getNotificationChannels();
     method @Nullable public String getNotificationDelegate();
     method public android.app.NotificationManager.Policy getNotificationPolicy();
-    method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public boolean isNotificationListenerAccessGranted(android.content.ComponentName);
     method public boolean isNotificationPolicyAccessGranted();
     method public void notify(int, android.app.Notification);
@@ -6418,7 +6422,7 @@
     method public android.content.pm.ServiceInfo getServiceInfo();
     method public String getServiceName();
     method public String getSettingsActivity();
-    method public android.net.Uri getSettingsSliceUri();
+    method @Nullable public android.net.Uri getSettingsSliceUri();
     method public boolean getShowMetadataInPreview();
     method public CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
     method public CharSequence loadContextDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException;
@@ -6489,7 +6493,7 @@
   }
 
   public interface ZygotePreload {
-    method public void doPreload(android.content.pm.ApplicationInfo);
+    method public void doPreload(@NonNull android.content.pm.ApplicationInfo);
   }
 
 }
@@ -9557,8 +9561,8 @@
     method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
     method public final int update(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
     method public static void validateSyncExtrasBundle(android.os.Bundle);
-    method public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
-    method public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
+    method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
+    method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
     field public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
     field public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
     field public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
@@ -10637,9 +10641,9 @@
   }
 
   public final class LocusId implements android.os.Parcelable {
-    ctor public LocusId(@NonNull android.net.Uri);
+    ctor public LocusId(@NonNull String);
     method public int describeContents();
-    method @NonNull public android.net.Uri getUri();
+    method @NonNull public String getId();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.LocusId> CREATOR;
   }
@@ -11457,7 +11461,7 @@
     method public int getSessionId();
     method public long getSize();
     method public int getStagedSessionErrorCode();
-    method public String getStagedSessionErrorMessage();
+    method @NonNull public String getStagedSessionErrorMessage();
     method public android.os.UserHandle getUser();
     method public boolean isActive();
     method public boolean isMultiPackage();
@@ -11824,25 +11828,25 @@
   }
 
   public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    ctor public PermissionGroupInfo();
-    ctor public PermissionGroupInfo(android.content.pm.PermissionGroupInfo);
+    ctor @Deprecated public PermissionGroupInfo();
+    ctor @Deprecated public PermissionGroupInfo(@NonNull android.content.pm.PermissionGroupInfo);
     method public int describeContents();
-    method public CharSequence loadDescription(android.content.pm.PackageManager);
+    method @Nullable public CharSequence loadDescription(@NonNull android.content.pm.PackageManager);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PermissionGroupInfo> CREATOR;
     field public static final int FLAG_PERSONAL_INFO = 1; // 0x1
-    field public int descriptionRes;
+    field @StringRes public int descriptionRes;
     field public int flags;
-    field public CharSequence nonLocalizedDescription;
+    field @Nullable public CharSequence nonLocalizedDescription;
     field public int priority;
   }
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    ctor public PermissionInfo();
-    ctor public PermissionInfo(android.content.pm.PermissionInfo);
+    ctor @Deprecated public PermissionInfo();
+    ctor @Deprecated public PermissionInfo(@NonNull android.content.pm.PermissionInfo);
     method public int describeContents();
     method public int getProtection();
     method public int getProtectionFlags();
-    method public CharSequence loadDescription(android.content.pm.PackageManager);
+    method @Nullable public CharSequence loadDescription(@NonNull android.content.pm.PackageManager);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.PermissionInfo> CREATOR;
     field public static final int FLAG_COSTS_MONEY = 1; // 0x1
     field public static final int FLAG_INSTALLED = 1073741824; // 0x40000000
@@ -11863,10 +11867,10 @@
     field public static final int PROTECTION_NORMAL = 0; // 0x0
     field public static final int PROTECTION_SIGNATURE = 2; // 0x2
     field @Deprecated public static final int PROTECTION_SIGNATURE_OR_SYSTEM = 3; // 0x3
-    field public int descriptionRes;
+    field @StringRes public int descriptionRes;
     field public int flags;
-    field public String group;
-    field public CharSequence nonLocalizedDescription;
+    field @Nullable public String group;
+    field @Nullable public CharSequence nonLocalizedDescription;
     field @Deprecated public int protectionLevel;
   }
 
@@ -11971,6 +11975,7 @@
     method @Nullable public android.content.Intent getIntent();
     method @Nullable public android.content.Intent[] getIntents();
     method public long getLastChangedTimestamp();
+    method @Nullable public android.content.LocusId getLocusId();
     method @Nullable public CharSequence getLongLabel();
     method @NonNull public String getPackage();
     method public int getRank();
@@ -12005,6 +12010,7 @@
     method @NonNull public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
     method @NonNull public android.content.pm.ShortcutInfo.Builder setIntent(@NonNull android.content.Intent);
     method @NonNull public android.content.pm.ShortcutInfo.Builder setIntents(@NonNull android.content.Intent[]);
+    method @NonNull public android.content.pm.ShortcutInfo.Builder setLocusId(@NonNull android.content.LocusId);
     method @NonNull public android.content.pm.ShortcutInfo.Builder setLongLabel(@NonNull CharSequence);
     method @NonNull public android.content.pm.ShortcutInfo.Builder setLongLived();
     method @NonNull public android.content.pm.ShortcutInfo.Builder setPerson(@NonNull android.app.Person);
@@ -14112,14 +14118,14 @@
   public class HardwareRenderer {
     ctor public HardwareRenderer();
     method public void clearContent();
-    method public android.graphics.HardwareRenderer.FrameRenderRequest createRenderRequest();
+    method @NonNull public android.graphics.HardwareRenderer.FrameRenderRequest createRenderRequest();
     method public void destroy();
     method public boolean isOpaque();
     method public void notifyFramePending();
     method public void setContentRoot(@Nullable android.graphics.RenderNode);
     method public void setLightSourceAlpha(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
     method public void setLightSourceGeometry(float, float, float, float);
-    method public void setName(String);
+    method public void setName(@NonNull String);
     method public void setOpaque(boolean);
     method public void setStopped(boolean);
     method public void setSurface(@Nullable android.view.Surface);
@@ -14131,9 +14137,9 @@
   }
 
   public final class HardwareRenderer.FrameRenderRequest {
-    method public android.graphics.HardwareRenderer.FrameRenderRequest setFrameCommitCallback(@NonNull java.util.concurrent.Executor, @NonNull Runnable);
-    method public android.graphics.HardwareRenderer.FrameRenderRequest setVsyncTime(long);
-    method public android.graphics.HardwareRenderer.FrameRenderRequest setWaitForPresent(boolean);
+    method @NonNull public android.graphics.HardwareRenderer.FrameRenderRequest setFrameCommitCallback(@NonNull java.util.concurrent.Executor, @NonNull Runnable);
+    method @NonNull public android.graphics.HardwareRenderer.FrameRenderRequest setVsyncTime(long);
+    method @NonNull public android.graphics.HardwareRenderer.FrameRenderRequest setWaitForPresent(boolean);
     method public int syncAndDraw();
   }
 
@@ -14155,6 +14161,7 @@
     method @Nullable public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener();
     method @Nullable public android.graphics.PostProcessor getPostProcessor();
     method public boolean isDecodeAsAlphaMaskEnabled();
+    method public static boolean isMimeTypeSupported(@NonNull String);
     method public boolean isMutableRequired();
     method public boolean isUnpremultipliedRequired();
     method public void setAllocator(int);
@@ -14951,8 +14958,8 @@
 
   public final class RenderNode {
     ctor public RenderNode(@Nullable String);
-    method public android.graphics.RecordingCanvas beginRecording(int, int);
-    method public android.graphics.RecordingCanvas beginRecording();
+    method @NonNull public android.graphics.RecordingCanvas beginRecording(int, int);
+    method @NonNull public android.graphics.RecordingCanvas beginRecording();
     method public long computeApproximateMemoryUsage();
     method public void discardDisplayList();
     method public void endRecording();
@@ -15005,7 +15012,7 @@
     method public boolean setPivotX(float);
     method public boolean setPivotY(float);
     method public boolean setPosition(int, int, int, int);
-    method public boolean setPosition(android.graphics.Rect);
+    method public boolean setPosition(@NonNull android.graphics.Rect);
     method public boolean setProjectBackwards(boolean);
     method public boolean setProjectionReceiver(boolean);
     method public boolean setRotationX(float);
@@ -15444,38 +15451,38 @@
     method public float getGradientCenterY();
     method public float getGradientRadius();
     method public int getGradientType();
-    method public int getInnerRadius();
+    method @Px public int getInnerRadius();
     method public float getInnerRadiusRatio();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
     method public int getShape();
-    method public int getThickness();
+    method @Px public int getThickness();
     method public float getThicknessRatio();
     method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(@ColorInt int);
     method public void setColor(@Nullable android.content.res.ColorStateList);
     method public void setColorFilter(@Nullable android.graphics.ColorFilter);
-    method public void setColors(@ColorInt int[]);
-    method public void setColors(@ColorInt int[], @Nullable float[]);
+    method public void setColors(@Nullable @ColorInt int[]);
+    method public void setColors(@Nullable @ColorInt int[], @Nullable float[]);
     method public void setCornerRadii(@Nullable float[]);
     method public void setCornerRadius(float);
     method public void setDither(boolean);
     method public void setGradientCenter(float, float);
     method public void setGradientRadius(float);
     method public void setGradientType(int);
-    method public void setInnerRadius(int);
-    method public void setInnerRadiusRatio(float);
+    method public void setInnerRadius(@Px int);
+    method public void setInnerRadiusRatio(@FloatRange(from=0.0f, fromInclusive=false) float);
     method public void setOrientation(android.graphics.drawable.GradientDrawable.Orientation);
-    method public void setPadding(int, int, int, int);
+    method public void setPadding(@Px int, @Px int, @Px int, @Px int);
     method public void setShape(int);
     method public void setSize(int, int);
     method public void setStroke(int, @ColorInt int);
     method public void setStroke(int, android.content.res.ColorStateList);
     method public void setStroke(int, @ColorInt int, float, float);
     method public void setStroke(int, android.content.res.ColorStateList, float, float);
-    method public void setThickness(int);
-    method public void setThicknessRatio(float);
+    method public void setThickness(@Px int);
+    method public void setThicknessRatio(@FloatRange(from=0.0f, fromInclusive=false) float);
     method public void setUseLevel(boolean);
     field public static final int LINE = 2; // 0x2
     field public static final int LINEAR_GRADIENT = 0; // 0x0
@@ -15688,10 +15695,10 @@
   public class StateListDrawable extends android.graphics.drawable.DrawableContainer {
     ctor public StateListDrawable();
     method public void addState(int[], android.graphics.drawable.Drawable);
-    method public int findStateDrawableIndex(int[]);
+    method public int findStateDrawableIndex(@NonNull int[]);
     method public int getStateCount();
-    method public android.graphics.drawable.Drawable getStateDrawable(int);
-    method public int[] getStateSet(int);
+    method @Nullable public android.graphics.drawable.Drawable getStateDrawable(int);
+    method @NonNull public int[] getStateSet(int);
   }
 
   public class TransitionDrawable extends android.graphics.drawable.LayerDrawable implements android.graphics.drawable.Drawable.Callback {
@@ -16560,10 +16567,10 @@
   public static class BiometricPrompt.Builder {
     ctor public BiometricPrompt.Builder(android.content.Context);
     method @NonNull public android.hardware.biometrics.BiometricPrompt build();
-    method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setAllowDeviceCredential(boolean);
+    method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setConfirmationRequired(boolean);
     method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setDescription(@NonNull CharSequence);
+    method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setDeviceCredentialAllowed(boolean);
     method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setNegativeButton(@NonNull CharSequence, @NonNull java.util.concurrent.Executor, @NonNull android.content.DialogInterface.OnClickListener);
-    method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setRequireConfirmation(boolean);
     method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setSubtitle(@NonNull CharSequence);
     method @NonNull public android.hardware.biometrics.BiometricPrompt.Builder setTitle(@NonNull CharSequence);
   }
@@ -16737,7 +16744,7 @@
   }
 
   public static final class CameraCharacteristics.Key<T> {
-    ctor public CameraCharacteristics.Key(String, Class<T>);
+    ctor public CameraCharacteristics.Key(@NonNull String, @NonNull Class<T>);
     method @NonNull public String getName();
   }
 
@@ -16796,6 +16803,7 @@
 
   public abstract static class CameraManager.AvailabilityCallback {
     ctor public CameraManager.AvailabilityCallback();
+    method public void onCameraAccessPrioritiesChanged();
     method public void onCameraAvailable(@NonNull String);
     method public void onCameraUnavailable(@NonNull String);
   }
@@ -17110,7 +17118,7 @@
   }
 
   public static final class CaptureRequest.Key<T> {
-    ctor public CaptureRequest.Key(String, Class<T>);
+    ctor public CaptureRequest.Key(@NonNull String, @NonNull Class<T>);
     method @NonNull public String getName();
   }
 
@@ -17205,7 +17213,7 @@
   }
 
   public static final class CaptureResult.Key<T> {
-    ctor public CaptureResult.Key(String, Class<T>);
+    ctor public CaptureResult.Key(@NonNull String, @NonNull Class<T>);
     method @NonNull public String getName();
   }
 
@@ -22823,24 +22831,6 @@
     method @Deprecated public boolean usedInFix();
   }
 
-  @Deprecated public final class GpsStatus {
-    method @Deprecated public int getMaxSatellites();
-    method @Deprecated public Iterable<android.location.GpsSatellite> getSatellites();
-    method @Deprecated public int getTimeToFirstFix();
-    field @Deprecated public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
-    field @Deprecated public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
-    field @Deprecated public static final int GPS_EVENT_STARTED = 1; // 0x1
-    field @Deprecated public static final int GPS_EVENT_STOPPED = 2; // 0x2
-  }
-
-  @Deprecated public static interface GpsStatus.Listener {
-    method @Deprecated public void onGpsStatusChanged(int);
-  }
-
-  @Deprecated public static interface GpsStatus.NmeaListener {
-    method @Deprecated public void onNmeaReceived(long, String);
-  }
-
   public class Location implements android.os.Parcelable {
     ctor public Location(String);
     ctor public Location(android.location.Location);
@@ -22909,55 +22899,50 @@
   }
 
   public class LocationManager {
-    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(android.location.OnNmeaMessageListener);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
-    method public void addTestProvider(String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
-    method @Deprecated public void clearTestProviderEnabled(String);
-    method @Deprecated public void clearTestProviderLocation(String);
-    method @Deprecated public void clearTestProviderStatus(String);
-    method public java.util.List<java.lang.String> getAllProviders();
-    method public String getBestProvider(android.location.Criteria, boolean);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(@NonNull android.location.OnNmeaMessageListener, @Nullable android.os.Handler);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
+    method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
+    method @Deprecated public void clearTestProviderEnabled(@NonNull String);
+    method @Deprecated public void clearTestProviderLocation(@NonNull String);
+    method @Deprecated public void clearTestProviderStatus(@NonNull String);
+    method @NonNull public java.util.List<java.lang.String> getAllProviders();
+    method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
     method @Nullable public String getGnssHardwareModelName();
     method public int getGnssYearOfHardware();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(String);
-    method public android.location.LocationProvider getProvider(String);
-    method public java.util.List<java.lang.String> getProviders(boolean);
-    method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) @Nullable public android.location.Location getLastKnownLocation(@NonNull String);
+    method @Nullable public android.location.LocationProvider getProvider(@NonNull String);
+    method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
+    method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
     method public boolean isLocationEnabled();
-    method public boolean isProviderEnabled(String);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
-    method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
-    method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
-    method @Deprecated public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
-    method public void removeNmeaListener(android.location.OnNmeaMessageListener);
-    method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(android.app.PendingIntent);
-    method public void removeTestProvider(String);
-    method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(android.location.LocationListener);
-    method public void removeUpdates(android.app.PendingIntent);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String, long, float, android.location.LocationListener);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(String, long, float, android.app.PendingIntent);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(String, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(String, android.app.PendingIntent);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(android.location.Criteria, android.app.PendingIntent);
-    method public boolean sendExtraCommand(String, String, android.os.Bundle);
-    method public void setTestProviderEnabled(String, boolean);
-    method public void setTestProviderLocation(String, android.location.Location);
-    method @Deprecated public void setTestProviderStatus(String, int, android.os.Bundle, long);
-    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
-    method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
+    method public boolean isProviderEnabled(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
+    method public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssStatusCallback(@NonNull android.location.GnssStatus.Callback, @Nullable android.os.Handler);
+    method public void removeNmeaListener(@NonNull android.location.OnNmeaMessageListener);
+    method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeProximityAlert(@NonNull android.app.PendingIntent);
+    method public void removeTestProvider(@NonNull String);
+    method @RequiresPermission(anyOf={"android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"}, apis="..22") public void removeUpdates(@NonNull android.location.LocationListener);
+    method public void removeUpdates(@NonNull android.app.PendingIntent);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.app.PendingIntent);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull android.location.Criteria, @NonNull android.app.PendingIntent);
+    method public boolean sendExtraCommand(@NonNull String, @NonNull String, @Nullable android.os.Bundle);
+    method public void setTestProviderEnabled(@NonNull String, boolean);
+    method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
+    method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
+    method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
+    method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
     field public static final String GPS_PROVIDER = "gps";
     field public static final String KEY_LOCATION_CHANGED = "location";
     field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -23016,6 +23001,7 @@
   }
 
   public final class AudioAttributes implements android.os.Parcelable {
+    method public boolean areHapticChannelsMuted();
     method public int describeContents();
     method public int getContentType();
     method public int getFlags();
@@ -23053,10 +23039,11 @@
     ctor public AudioAttributes.Builder();
     ctor public AudioAttributes.Builder(android.media.AudioAttributes);
     method public android.media.AudioAttributes build();
-    method public android.media.AudioAttributes.Builder setAllowCapture(boolean);
+    method @NonNull public android.media.AudioAttributes.Builder setAllowCapture(boolean);
     method public android.media.AudioAttributes.Builder setContentType(int);
     method public android.media.AudioAttributes.Builder setFlags(int);
     method public android.media.AudioAttributes.Builder setLegacyStreamType(int);
+    method public android.media.AudioAttributes.Builder setMuteHapticChannels(boolean);
     method public android.media.AudioAttributes.Builder setUsage(int);
   }
 
@@ -23392,11 +23379,11 @@
 
   public static final class AudioPlaybackCaptureConfiguration.Builder {
     ctor public AudioPlaybackCaptureConfiguration.Builder(@NonNull android.media.projection.MediaProjection);
-    method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
-    method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
-    method public android.media.AudioPlaybackCaptureConfiguration build();
-    method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
-    method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration build();
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes);
   }
 
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
@@ -23497,7 +23484,7 @@
     ctor public AudioRecord.Builder();
     method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
     method public android.media.AudioRecord.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException;
-    method public android.media.AudioRecord.Builder setAudioPlaybackCaptureConfig(@NonNull android.media.AudioPlaybackCaptureConfiguration);
+    method @NonNull public android.media.AudioRecord.Builder setAudioPlaybackCaptureConfig(@NonNull android.media.AudioPlaybackCaptureConfiguration);
     method public android.media.AudioRecord.Builder setAudioSource(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
   }
@@ -23569,7 +23556,6 @@
     method @Deprecated public void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
     method public int attachAuxEffect(int);
     method @NonNull public android.media.VolumeShaper createVolumeShaper(@NonNull android.media.VolumeShaper.Configuration);
-    method @Deprecated public static void deprecateStreamTypeForPlayback(int, @NonNull String, @NonNull String) throws java.lang.IllegalArgumentException;
     method protected void finalize();
     method public void flush();
     method @NonNull public android.media.AudioAttributes getAudioAttributes();
@@ -23689,18 +23675,18 @@
 
   public abstract static class AudioTrack.StreamEventCallback {
     ctor public AudioTrack.StreamEventCallback();
-    method public void onDataRequest(@NonNull android.media.AudioTrack, int);
+    method public void onDataRequest(@NonNull android.media.AudioTrack, @IntRange(from=0) int);
     method public void onPresentationEnded(@NonNull android.media.AudioTrack);
     method public void onTearDown(@NonNull android.media.AudioTrack);
   }
 
   public class CallbackDataSourceDesc extends android.media.DataSourceDesc {
-    method public android.media.DataSourceCallback getDataSourceCallback();
+    method @NonNull public android.media.DataSourceCallback getDataSourceCallback();
   }
 
   public static class CallbackDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.CallbackDataSourceDesc.Builder> {
     ctor public CallbackDataSourceDesc.Builder();
-    ctor public CallbackDataSourceDesc.Builder(android.media.CallbackDataSourceDesc);
+    ctor public CallbackDataSourceDesc.Builder(@Nullable android.media.CallbackDataSourceDesc);
     method @NonNull public android.media.CallbackDataSourceDesc build();
     method @NonNull public android.media.CallbackDataSourceDesc.Builder setDataSource(@NonNull android.media.DataSourceCallback);
   }
@@ -23760,12 +23746,12 @@
   public abstract class DataSourceCallback implements java.io.Closeable {
     ctor public DataSourceCallback();
     method public abstract long getSize() throws java.io.IOException;
-    method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
+    method public abstract int readAt(long, @NonNull byte[], int, int) throws java.io.IOException;
   }
 
   public class DataSourceDesc {
     method public long getEndPosition();
-    method public String getMediaId();
+    method @Nullable public String getMediaId();
     method public long getStartPosition();
     field public static final long LONG_MAX_TIME_MS = 576460752303423L; // 0x20c49ba5e353fL
     field public static final long POSITION_UNKNOWN = 576460752303423L; // 0x20c49ba5e353fL
@@ -23773,7 +23759,7 @@
 
   protected static class DataSourceDesc.BuilderBase<T extends android.media.DataSourceDesc.BuilderBase> {
     method @NonNull public T setEndPosition(long);
-    method @NonNull public T setMediaId(String);
+    method @NonNull public T setMediaId(@Nullable String);
     method @NonNull public T setStartPosition(long);
   }
 
@@ -23806,7 +23792,7 @@
     method public android.graphics.Bitmap getThumbnailBitmap();
     method public byte[] getThumbnailBytes();
     method @Nullable public long[] getThumbnailRange();
-    method public boolean hasAttribute(String);
+    method public boolean hasAttribute(@NonNull String);
     method public boolean hasThumbnail();
     method public boolean isThumbnailCompressed();
     method public void saveAttributes() throws java.io.IOException;
@@ -23982,13 +23968,13 @@
   public class FileDataSourceDesc extends android.media.DataSourceDesc {
     method public long getLength();
     method public long getOffset();
-    method public android.os.ParcelFileDescriptor getParcelFileDescriptor();
+    method @NonNull public android.os.ParcelFileDescriptor getParcelFileDescriptor();
     field public static final long FD_LENGTH_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
   public static class FileDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.FileDataSourceDesc.Builder> {
     ctor public FileDataSourceDesc.Builder();
-    ctor public FileDataSourceDesc.Builder(android.media.FileDataSourceDesc);
+    ctor public FileDataSourceDesc.Builder(@Nullable android.media.FileDataSourceDesc);
     method @NonNull public android.media.FileDataSourceDesc build();
     method @NonNull public android.media.FileDataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor);
     method @NonNull public android.media.FileDataSourceDesc.Builder setDataSource(@NonNull android.os.ParcelFileDescriptor, long, long);
@@ -24664,7 +24650,7 @@
     ctor public MediaController2(@NonNull android.content.Context, @NonNull android.media.Session2Token, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaController2.ControllerCallback);
     method public void cancelSessionCommand(@NonNull Object);
     method public void close();
-    method public android.media.Session2Token getConnectedSessionToken();
+    method @Nullable public android.media.Session2Token getConnectedSessionToken();
     method public boolean isPlaybackActive();
     method @NonNull public Object sendSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
   }
@@ -25138,7 +25124,7 @@
     field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
   }
 
-  public static class MediaItem2.Builder {
+  public static final class MediaItem2.Builder {
     ctor public MediaItem2.Builder();
     method @NonNull public android.media.MediaItem2 build();
     method @NonNull public android.media.MediaItem2.Builder setEndPosition(long);
@@ -25326,7 +25312,6 @@
     method public static android.media.MediaPlayer create(android.content.Context, int);
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
     method @NonNull public android.media.VolumeShaper createVolumeShaper(@NonNull android.media.VolumeShaper.Configuration);
-    method @Deprecated public static void deprecateStreamTypeForPlayback(int, @NonNull String, @NonNull String) throws java.lang.IllegalArgumentException;
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method protected void finalize();
     method public int getAudioSessionId();
@@ -25540,16 +25525,16 @@
   }
 
   public class MediaPlayer2 implements android.media.AudioRouting java.lang.AutoCloseable {
-    ctor public MediaPlayer2(android.content.Context);
-    method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
-    method public Object attachAuxEffect(int);
+    ctor public MediaPlayer2(@NonNull android.content.Context);
+    method public void addOnRoutingChangedListener(@NonNull android.media.AudioRouting.OnRoutingChangedListener, @Nullable android.os.Handler);
+    method @NonNull public Object attachAuxEffect(int);
     method public boolean cancelCommand(@NonNull Object);
     method public void clearDrmEventCallback();
-    method public Object clearNextDataSources();
+    method @NonNull public Object clearNextDataSources();
     method public void clearPendingCommands();
     method public void close();
-    method public Object deselectTrack(int);
-    method public Object deselectTrack(@NonNull android.media.DataSourceDesc, int);
+    method @NonNull public Object deselectTrack(int);
+    method @NonNull public Object deselectTrack(@NonNull android.media.DataSourceDesc, int);
     method @NonNull public android.media.AudioAttributes getAudioAttributes();
     method public int getAudioSessionId();
     method public long getBufferedPosition();
@@ -25559,11 +25544,11 @@
     method public long getDuration();
     method public long getDuration(@NonNull android.media.DataSourceDesc);
     method public float getMaxPlayerVolume();
-    method public android.os.PersistableBundle getMetrics();
+    method @Nullable public android.os.PersistableBundle getMetrics();
     method @NonNull public android.media.PlaybackParams getPlaybackParams();
     method public float getPlayerVolume();
-    method public android.media.AudioDeviceInfo getPreferredDevice();
-    method public android.media.AudioDeviceInfo getRoutedDevice();
+    method @Nullable public android.media.AudioDeviceInfo getPreferredDevice();
+    method @Nullable public android.media.AudioDeviceInfo getRoutedDevice();
     method public int getSelectedTrack(int);
     method public int getSelectedTrack(@NonNull android.media.DataSourceDesc, int);
     method public int getState();
@@ -25571,37 +25556,37 @@
     method @Nullable public android.media.MediaTimestamp getTimestamp();
     method @NonNull public java.util.List<android.media.MediaPlayer2.TrackInfo> getTrackInfo();
     method @NonNull public java.util.List<android.media.MediaPlayer2.TrackInfo> getTrackInfo(@NonNull android.media.DataSourceDesc);
-    method public android.util.Size getVideoSize();
+    method @NonNull public android.util.Size getVideoSize();
     method public boolean isLooping();
-    method public Object loopCurrent(boolean);
-    method public Object notifyWhenCommandLabelReached(@NonNull Object);
-    method public Object pause();
-    method public Object play();
-    method public Object prepare();
+    method @NonNull public Object loopCurrent(boolean);
+    method @NonNull public Object notifyWhenCommandLabelReached(@NonNull Object);
+    method @NonNull public Object pause();
+    method @NonNull public Object play();
+    method @NonNull public Object prepare();
     method public void registerEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaPlayer2.EventCallback);
-    method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
+    method public void removeOnRoutingChangedListener(@NonNull android.media.AudioRouting.OnRoutingChangedListener);
     method public void reset();
-    method public Object seekTo(long);
-    method public Object seekTo(long, int);
-    method public Object selectTrack(int);
-    method public Object selectTrack(@NonNull android.media.DataSourceDesc, int);
-    method public Object setAudioAttributes(@NonNull android.media.AudioAttributes);
-    method public Object setAudioSessionId(int);
-    method public Object setAuxEffectSendLevel(float);
-    method public Object setDataSource(@NonNull android.media.DataSourceDesc);
-    method public Object setDisplay(android.view.SurfaceHolder);
+    method @NonNull public Object seekTo(long);
+    method @NonNull public Object seekTo(long, int);
+    method @NonNull public Object selectTrack(int);
+    method @NonNull public Object selectTrack(@NonNull android.media.DataSourceDesc, int);
+    method @NonNull public Object setAudioAttributes(@NonNull android.media.AudioAttributes);
+    method @NonNull public Object setAudioSessionId(int);
+    method @NonNull public Object setAuxEffectSendLevel(float);
+    method @NonNull public Object setDataSource(@NonNull android.media.DataSourceDesc);
+    method @NonNull public Object setDisplay(@Nullable android.view.SurfaceHolder);
     method public void setDrmEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaPlayer2.DrmEventCallback);
-    method public Object setNextDataSource(@NonNull android.media.DataSourceDesc);
-    method public Object setNextDataSources(@NonNull java.util.List<android.media.DataSourceDesc>);
-    method public Object setPlaybackParams(@NonNull android.media.PlaybackParams);
-    method public Object setPlayerVolume(float);
-    method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
-    method public Object setScreenOnWhilePlaying(boolean);
-    method public Object setSurface(android.view.Surface);
-    method public Object setSyncParams(@NonNull android.media.SyncParams);
-    method public Object setWakeLock(@NonNull android.os.PowerManager.WakeLock);
-    method public Object skipToNext();
-    method public void unregisterEventCallback(android.media.MediaPlayer2.EventCallback);
+    method @NonNull public Object setNextDataSource(@NonNull android.media.DataSourceDesc);
+    method @NonNull public Object setNextDataSources(@NonNull java.util.List<android.media.DataSourceDesc>);
+    method @NonNull public Object setPlaybackParams(@NonNull android.media.PlaybackParams);
+    method @NonNull public Object setPlayerVolume(float);
+    method public boolean setPreferredDevice(@Nullable android.media.AudioDeviceInfo);
+    method @NonNull public Object setScreenOnWhilePlaying(boolean);
+    method @NonNull public Object setSurface(@Nullable android.view.Surface);
+    method @NonNull public Object setSyncParams(@NonNull android.media.SyncParams);
+    method @NonNull public Object setWakeLock(@NonNull android.os.PowerManager.WakeLock);
+    method @NonNull public Object skipToNext();
+    method public void unregisterEventCallback(@NonNull android.media.MediaPlayer2.EventCallback);
     field public static final int CALL_COMPLETED_ATTACH_AUX_EFFECT = 1; // 0x1
     field public static final int CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES = 30; // 0x1e
     field public static final int CALL_COMPLETED_DESELECT_TRACK = 2; // 0x2
@@ -25736,8 +25721,8 @@
   }
 
   public static class MediaPlayer2.TrackInfo {
-    method public android.media.MediaFormat getFormat();
-    method public String getLanguage();
+    method @Nullable public android.media.MediaFormat getFormat();
+    method @Nullable public String getLanguage();
     method public int getTrackType();
     field public static final int MEDIA_TRACK_TYPE_AUDIO = 2; // 0x2
     field public static final int MEDIA_TRACK_TYPE_METADATA = 5; // 0x5
@@ -26421,7 +26406,6 @@
     ctor @Deprecated public SoundPool(int, int, int);
     method public final void autoPause();
     method public final void autoResume();
-    method @Deprecated public static void deprecateStreamTypeForPlayback(int, @NonNull String, @NonNull String) throws java.lang.IllegalArgumentException;
     method protected void finalize();
     method public int load(String, int);
     method public int load(android.content.Context, int, int);
@@ -26617,15 +26601,15 @@
   }
 
   public class UriDataSourceDesc extends android.media.DataSourceDesc {
-    method public android.content.Context getContext();
-    method public java.util.List<java.net.HttpCookie> getCookies();
-    method public java.util.Map<java.lang.String,java.lang.String> getHeaders();
-    method public android.net.Uri getUri();
+    method @NonNull public android.content.Context getContext();
+    method @Nullable public java.util.List<java.net.HttpCookie> getCookies();
+    method @Nullable public java.util.Map<java.lang.String,java.lang.String> getHeaders();
+    method @NonNull public android.net.Uri getUri();
   }
 
   public static class UriDataSourceDesc.Builder extends android.media.DataSourceDesc.BuilderBase<android.media.UriDataSourceDesc.Builder> {
     ctor public UriDataSourceDesc.Builder();
-    ctor public UriDataSourceDesc.Builder(android.media.UriDataSourceDesc);
+    ctor public UriDataSourceDesc.Builder(@Nullable android.media.UriDataSourceDesc);
     method @NonNull public android.media.UriDataSourceDesc build();
     method @NonNull public android.media.UriDataSourceDesc.Builder setDataSource(@NonNull android.content.Context, @NonNull android.net.Uri);
     method @NonNull public android.media.UriDataSourceDesc.Builder setDataSource(@NonNull android.content.Context, @NonNull android.net.Uri, @Nullable java.util.Map<java.lang.String,java.lang.String>, @Nullable java.util.List<java.net.HttpCookie>);
@@ -28980,6 +28964,7 @@
     field public static final int NET_CAPABILITY_IA = 7; // 0x7
     field public static final int NET_CAPABILITY_IMS = 4; // 0x4
     field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc
+    field public static final int NET_CAPABILITY_MCX = 23; // 0x17
     field public static final int NET_CAPABILITY_MMS = 0; // 0x0
     field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14
     field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb
@@ -29402,7 +29387,7 @@
     method public java.util.Date getValidNotAfterDate();
     method @Deprecated public String getValidNotBefore();
     method public java.util.Date getValidNotBeforeDate();
-    method public java.security.cert.X509Certificate getX509Certificate();
+    method @Nullable public java.security.cert.X509Certificate getX509Certificate();
     method public static android.net.http.SslCertificate restoreState(android.os.Bundle);
     method public static android.os.Bundle saveState(android.net.http.SslCertificate);
   }
@@ -29805,13 +29790,13 @@
     field @Deprecated public String BSSID;
     field @Deprecated public String FQDN;
     field @Deprecated public String SSID;
-    field @Deprecated public java.util.BitSet allowedAuthAlgorithms;
-    field @Deprecated public java.util.BitSet allowedGroupCiphers;
-    field @Deprecated public java.util.BitSet allowedGroupManagementCiphers;
-    field @Deprecated public java.util.BitSet allowedKeyManagement;
-    field @Deprecated public java.util.BitSet allowedPairwiseCiphers;
-    field @Deprecated public java.util.BitSet allowedProtocols;
-    field @Deprecated public java.util.BitSet allowedSuiteBCiphers;
+    field @Deprecated @NonNull public java.util.BitSet allowedAuthAlgorithms;
+    field @Deprecated @NonNull public java.util.BitSet allowedGroupCiphers;
+    field @Deprecated @NonNull public java.util.BitSet allowedGroupManagementCiphers;
+    field @Deprecated @NonNull public java.util.BitSet allowedKeyManagement;
+    field @Deprecated @NonNull public java.util.BitSet allowedPairwiseCiphers;
+    field @Deprecated @NonNull public java.util.BitSet allowedProtocols;
+    field @Deprecated @NonNull public java.util.BitSet allowedSuiteBCiphers;
     field @Deprecated public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field @Deprecated public boolean hiddenSSID;
     field @Deprecated public boolean isHomeProviderNetwork;
@@ -30266,7 +30251,7 @@
     field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
   }
 
-  public static class WifiAwareManager.NetworkSpecifierBuilder {
+  public static final class WifiAwareManager.NetworkSpecifierBuilder {
     ctor public WifiAwareManager.NetworkSpecifierBuilder();
     method @NonNull public android.net.NetworkSpecifier build();
     method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setDiscoverySession(@NonNull android.net.wifi.aware.DiscoverySession);
@@ -30421,13 +30406,13 @@
 
   public static final class WifiP2pConfig.Builder {
     ctor public WifiP2pConfig.Builder();
-    method public android.net.wifi.p2p.WifiP2pConfig build();
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(android.net.MacAddress);
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int);
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingFrequency(int);
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(String);
-    method public android.net.wifi.p2p.WifiP2pConfig.Builder setPassphrase(String);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig build();
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(@Nullable android.net.MacAddress);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingFrequency(int);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(@NonNull String);
+    method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setPassphrase(@NonNull String);
   }
 
   public class WifiP2pDevice implements android.os.Parcelable {
@@ -30555,7 +30540,7 @@
   }
 
   public static interface WifiP2pManager.DeviceInfoListener {
-    method public void onDeviceInfoAvailable(android.net.wifi.p2p.WifiP2pDevice);
+    method public void onDeviceInfoAvailable(@Nullable android.net.wifi.p2p.WifiP2pDevice);
   }
 
   public static interface WifiP2pManager.DiscoveryStateListener {
@@ -30637,6 +30622,41 @@
 
 package android.net.wifi.rtt {
 
+  public class CivicLocationKeys {
+    field public static final int ADDITIONAL_CODE = 32; // 0x20
+    field public static final int APT = 26; // 0x1a
+    field public static final int BOROUGH = 4; // 0x4
+    field public static final int BRANCH_ROAD_NAME = 36; // 0x24
+    field public static final int BUILDING = 25; // 0x19
+    field public static final int CITY = 3; // 0x3
+    field public static final int COUNTY = 2; // 0x2
+    field public static final int DESK = 33; // 0x21
+    field public static final int FLOOR = 27; // 0x1b
+    field public static final int GROUP_OF_STREETS = 6; // 0x6
+    field public static final int HNO = 19; // 0x13
+    field public static final int HNS = 20; // 0x14
+    field public static final int LANGUAGE = 0; // 0x0
+    field public static final int LMK = 21; // 0x15
+    field public static final int LOC = 22; // 0x16
+    field public static final int NAM = 23; // 0x17
+    field public static final int NEIGHBORHOOD = 5; // 0x5
+    field public static final int PCN = 30; // 0x1e
+    field public static final int POD = 17; // 0x11
+    field public static final int POSTAL_CODE = 24; // 0x18
+    field public static final int PO_BOX = 31; // 0x1f
+    field public static final int PRD = 16; // 0x10
+    field public static final int PRIMARY_ROAD_NAME = 34; // 0x22
+    field public static final int ROAD_SECTION = 35; // 0x23
+    field public static final int ROOM = 28; // 0x1c
+    field public static final int SCRIPT = 128; // 0x80
+    field public static final int STATE = 1; // 0x1
+    field public static final int STREET_NAME_POST_MODIFIER = 39; // 0x27
+    field public static final int STREET_NAME_PRE_MODIFIER = 38; // 0x26
+    field public static final int STS = 18; // 0x12
+    field public static final int SUBBRANCH_ROAD_NAME = 37; // 0x25
+    field public static final int TYPE_OF_PLACE = 29; // 0x1d
+  }
+
   public final class RangingRequest implements android.os.Parcelable {
     method public int describeContents();
     method public static int getMaxPeers();
@@ -30662,9 +30682,9 @@
     method public int getNumSuccessfulMeasurements();
     method @Nullable public android.net.wifi.aware.PeerHandle getPeerHandle();
     method public long getRangingTimestampMillis();
-    method @Nullable public android.net.wifi.rtt.ResponderLocation getResponderLocation();
     method public int getRssi();
     method public int getStatus();
+    method @Nullable public android.net.wifi.rtt.ResponderLocation getUnverifiedResponderLocation();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingResult> CREATOR;
     field public static final int STATUS_FAIL = 1; // 0x1
@@ -30687,19 +30707,25 @@
     method public double getAltitudeUncertainty();
     method public java.util.List<android.net.MacAddress> getColocatedBssids();
     method public int getDatum();
+    method public boolean getDependentStationIndication();
     method public int getExpectedToMove();
+    method public double getFloorNumber();
+    method public double getHeightAboveFloorMeters();
+    method public double getHeightAboveFloorUncertaintyMeters();
     method public double getLatitude();
     method public double getLatitudeUncertainty();
-    method public int getLciFlags();
+    method public int getLciVersion();
     method public double getLongitude();
     method public double getLongitudeUncertainty();
-    method public int getMapImageType();
-    method @Nullable public java.net.URL getMapImageUrl();
-    method public double getStaFloorNumber();
-    method public double getStaHeightAboveFloorMeters();
-    method public double getStaHeightAboveFloorUncertaintyMeters();
+    method @Nullable public String getMapImageMimeType();
+    method @Nullable public android.net.Uri getMapImageUri();
+    method public boolean getRegisteredLocationAgreementIndication();
+    method public boolean getRegisteredLocationDseIndication();
     method public boolean isLciSubelementValid();
-    method public boolean isZsubelementValid();
+    method public boolean isZaxisSubelementValid();
+    method @Nullable public android.location.Address toCivicLocationAddress();
+    method @Nullable public android.util.SparseArray toCivicLocationSparseArray();
+    method @NonNull public android.location.Location toLocation();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALTITUDE_FLOORS = 2; // 0x2
     field public static final int ALTITUDE_METERS = 1; // 0x1
@@ -30709,33 +30735,11 @@
     field public static final int DATUM_NAD83_NAV88 = 2; // 0x2
     field public static final int DATUM_UNDEFINED = 0; // 0x0
     field public static final int DATUM_WGS84 = 1; // 0x1
-    field public static final int LCI_FLAGS_MASK_DEPENDENT_STA = 4; // 0x4
-    field public static final int LCI_FLAGS_MASK_REGLOC_AGREEMENT = 16; // 0x10
-    field public static final int LCI_FLAGS_MASK_REGLOC_DSE = 8; // 0x8
-    field public static final int LCI_FLAGS_MASK_VERSION = 3; // 0x3
     field public static final int LCI_VERSION_1 = 1; // 0x1
     field public static final int LOCATION_FIXED = 0; // 0x0
     field public static final int LOCATION_MOVEMENT_UNKNOWN = 2; // 0x2
     field public static final int LOCATION_RESERVED = 3; // 0x3
     field public static final int LOCATION_VARIABLE = 1; // 0x1
-    field public static final int MAP_TYPE_BMP = 12; // 0xc
-    field public static final int MAP_TYPE_CAD = 8; // 0x8
-    field public static final int MAP_TYPE_DWF = 7; // 0x7
-    field public static final int MAP_TYPE_DWG = 6; // 0x6
-    field public static final int MAP_TYPE_DXF = 5; // 0x5
-    field public static final int MAP_TYPE_GIF = 2; // 0x2
-    field public static final int MAP_TYPE_GML = 10; // 0xa
-    field public static final int MAP_TYPE_ICO = 17; // 0x11
-    field public static final int MAP_TYPE_JPG = 3; // 0x3
-    field public static final int MAP_TYPE_KML = 11; // 0xb
-    field public static final int MAP_TYPE_PGM = 13; // 0xd
-    field public static final int MAP_TYPE_PNG = 1; // 0x1
-    field public static final int MAP_TYPE_PPM = 14; // 0xe
-    field public static final int MAP_TYPE_SVG = 4; // 0x4
-    field public static final int MAP_TYPE_TIFF = 9; // 0x9
-    field public static final int MAP_TYPE_URL_DEFINED = 0; // 0x0
-    field public static final int MAP_TYPE_XBM = 15; // 0xf
-    field public static final int MAP_TYPE_XPM = 16; // 0x10
   }
 
   public class WifiRttManager {
@@ -35525,7 +35529,7 @@
 
   public abstract class VibrationEffect implements android.os.Parcelable {
     method public static android.os.VibrationEffect createOneShot(long, int);
-    method public static android.os.VibrationEffect createPredefined(int);
+    method @NonNull public static android.os.VibrationEffect createPredefined(int);
     method public static android.os.VibrationEffect createWaveform(long[], int);
     method public static android.os.VibrationEffect createWaveform(long[], int[], int);
     method public int describeContents();
@@ -38329,10 +38333,10 @@
     method public android.database.Cursor queryChildDocuments(String, @Nullable String[], @Nullable android.os.Bundle) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryDocument(String, String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor queryRecentDocuments(String, String[]) throws java.io.FileNotFoundException;
-    method public android.database.Cursor queryRecentDocuments(String, String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
+    method @Nullable public android.database.Cursor queryRecentDocuments(@NonNull String, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(String, String, String[]) throws java.io.FileNotFoundException;
-    method public android.database.Cursor querySearchDocuments(@NonNull String, @Nullable String[], @NonNull android.os.Bundle) throws java.io.FileNotFoundException;
+    method @Nullable public android.database.Cursor querySearchDocuments(@NonNull String, @Nullable String[], @NonNull android.os.Bundle) throws java.io.FileNotFoundException;
     method public void removeDocument(String, String) throws java.io.FileNotFoundException;
     method public String renameDocument(String, String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(String);
@@ -38419,7 +38423,8 @@
     method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri);
     method public static android.net.Uri getMediaScannerUri();
     method @Nullable public static android.net.Uri getMediaUri(@NonNull android.content.Context, @NonNull android.net.Uri);
-    method public static String getVersion(android.content.Context);
+    method @NonNull public static String getVersion(@NonNull android.content.Context);
+    method @NonNull public static String getVersion(@NonNull android.content.Context, @NonNull String);
     method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
@@ -38429,7 +38434,7 @@
     field public static final String ACTION_REVIEW_SECURE = "android.provider.action.REVIEW_SECURE";
     field public static final String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final String AUTHORITY = "media";
-    field public static final android.net.Uri AUTHORITY_URI;
+    field @NonNull public static final android.net.Uri AUTHORITY_URI;
     field public static final String EXTRA_BRIGHTNESS = "android.provider.extra.BRIGHTNESS";
     field public static final String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
     field public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
@@ -41388,7 +41393,7 @@
 
   public class CarrierIdentifier implements android.os.Parcelable {
     ctor public CarrierIdentifier(String, String, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
-    ctor public CarrierIdentifier(String, String, @Nullable String, @Nullable String, @Nullable String, @Nullable String, int, int);
+    ctor public CarrierIdentifier(@NonNull String, @NonNull String, @Nullable String, @Nullable String, @Nullable String, @Nullable String, int, int);
     ctor public CarrierIdentifier(byte[], @Nullable String, @Nullable String);
     method public int describeContents();
     method public int getCarrierId();
@@ -41596,23 +41601,6 @@
 
 package android.service.notification {
 
-  public final class Adjustment implements android.os.Parcelable {
-    ctor public Adjustment(@NonNull String, @NonNull String, @NonNull android.os.Bundle, @NonNull CharSequence, @NonNull android.os.UserHandle);
-    method public int describeContents();
-    method @NonNull public CharSequence getExplanation();
-    method @NonNull public String getKey();
-    method @NonNull public String getPackage();
-    method @NonNull public android.os.Bundle getSignals();
-    method @NonNull public android.os.UserHandle getUserHandle();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
-    field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
-    field public static final String KEY_IMPORTANCE = "key_importance";
-    field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
-    field public static final String KEY_TEXT_REPLIES = "key_text_replies";
-    field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
-  }
-
   public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, String, int);
     ctor public Condition(android.net.Uri, String, String, String, int, int, int);
@@ -41659,26 +41647,6 @@
     field @Deprecated public static final String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
-  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationAssistantService();
-    method public final void adjustNotification(@NonNull android.service.notification.Adjustment);
-    method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>);
-    method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
-    method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
-    method public void onNotificationDirectReplied(@NonNull String);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
-    method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
-    method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
-    method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
-    method public abstract void onNotificationSnoozedUntilContext(android.service.notification.StatusBarNotification, String);
-    method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
-    method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
-    method public final void unsnoozeNotification(String);
-    field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
-    field public static final int SOURCE_FROM_APP = 0; // 0x0
-    field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
-  }
-
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -41781,37 +41749,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
   }
 
-  public final class NotificationStats implements android.os.Parcelable {
-    ctor public NotificationStats();
-    method public int describeContents();
-    method public int getDismissalSentiment();
-    method public int getDismissalSurface();
-    method public boolean hasDirectReplied();
-    method public boolean hasExpanded();
-    method public boolean hasInteracted();
-    method public boolean hasSeen();
-    method public boolean hasSnoozed();
-    method public boolean hasViewedSettings();
-    method public void setDirectReplied();
-    method public void setDismissalSentiment(int);
-    method public void setDismissalSurface(int);
-    method public void setExpanded();
-    method public void setSeen();
-    method public void setSnoozed();
-    method public void setViewedSettings();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
-    field public static final int DISMISSAL_AOD = 2; // 0x2
-    field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
-    field public static final int DISMISSAL_OTHER = 0; // 0x0
-    field public static final int DISMISSAL_PEEK = 1; // 0x1
-    field public static final int DISMISSAL_SHADE = 3; // 0x3
-    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
-    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
-    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
-    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
-  }
-
   public class StatusBarNotification implements android.os.Parcelable {
     ctor @Deprecated public StatusBarNotification(String, String, int, String, int, int, int, android.app.Notification, android.os.UserHandle, long);
     ctor public StatusBarNotification(android.os.Parcel);
@@ -41868,28 +41805,28 @@
     field public static final int STATE_UNSET = 0; // 0x0
   }
 
-  public static class ZenPolicy.Builder {
+  public static final class ZenPolicy.Builder {
     ctor public ZenPolicy.Builder();
-    method public android.service.notification.ZenPolicy.Builder allowAlarms(boolean);
-    method public android.service.notification.ZenPolicy.Builder allowAllSounds();
-    method public android.service.notification.ZenPolicy.Builder allowCalls(int);
-    method public android.service.notification.ZenPolicy.Builder allowEvents(boolean);
-    method public android.service.notification.ZenPolicy.Builder allowMedia(boolean);
-    method public android.service.notification.ZenPolicy.Builder allowMessages(int);
-    method public android.service.notification.ZenPolicy.Builder allowReminders(boolean);
-    method public android.service.notification.ZenPolicy.Builder allowRepeatCallers(boolean);
-    method public android.service.notification.ZenPolicy.Builder allowSystem(boolean);
-    method public android.service.notification.ZenPolicy build();
-    method public android.service.notification.ZenPolicy.Builder disallowAllSounds();
-    method public android.service.notification.ZenPolicy.Builder hideAllVisualEffects();
-    method public android.service.notification.ZenPolicy.Builder showAllVisualEffects();
-    method public android.service.notification.ZenPolicy.Builder showBadges(boolean);
-    method public android.service.notification.ZenPolicy.Builder showFullScreenIntent(boolean);
-    method public android.service.notification.ZenPolicy.Builder showInAmbientDisplay(boolean);
-    method public android.service.notification.ZenPolicy.Builder showInNotificationList(boolean);
-    method public android.service.notification.ZenPolicy.Builder showLights(boolean);
-    method public android.service.notification.ZenPolicy.Builder showPeeking(boolean);
-    method public android.service.notification.ZenPolicy.Builder showStatusBarIcons(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowAlarms(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowAllSounds();
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowCalls(int);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowEvents(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowMedia(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowMessages(int);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowReminders(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowRepeatCallers(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder allowSystem(boolean);
+    method @NonNull public android.service.notification.ZenPolicy build();
+    method @NonNull public android.service.notification.ZenPolicy.Builder disallowAllSounds();
+    method @NonNull public android.service.notification.ZenPolicy.Builder hideAllVisualEffects();
+    method @NonNull public android.service.notification.ZenPolicy.Builder showAllVisualEffects();
+    method @NonNull public android.service.notification.ZenPolicy.Builder showBadges(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showFullScreenIntent(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showInAmbientDisplay(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showInNotificationList(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showLights(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showPeeking(boolean);
+    method @NonNull public android.service.notification.ZenPolicy.Builder showStatusBarIcons(boolean);
   }
 
 }
@@ -43355,14 +43292,14 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telecom.CallIdentification> CREATOR;
   }
 
-  public static class CallIdentification.Builder {
+  public static final class CallIdentification.Builder {
     ctor public CallIdentification.Builder();
-    method public android.telecom.CallIdentification build();
-    method public android.telecom.CallIdentification.Builder setDescription(@Nullable CharSequence);
-    method public android.telecom.CallIdentification.Builder setDetails(@Nullable CharSequence);
-    method public android.telecom.CallIdentification.Builder setName(@Nullable CharSequence);
-    method public android.telecom.CallIdentification.Builder setNuisanceConfidence(int);
-    method public android.telecom.CallIdentification.Builder setPhoto(@Nullable android.graphics.drawable.Icon);
+    method @NonNull public android.telecom.CallIdentification build();
+    method @NonNull public android.telecom.CallIdentification.Builder setDescription(@Nullable CharSequence);
+    method @NonNull public android.telecom.CallIdentification.Builder setDetails(@Nullable CharSequence);
+    method @NonNull public android.telecom.CallIdentification.Builder setName(@Nullable CharSequence);
+    method @NonNull public android.telecom.CallIdentification.Builder setNuisanceConfidence(int);
+    method @NonNull public android.telecom.CallIdentification.Builder setPhoto(@Nullable android.graphics.drawable.Icon);
   }
 
   public abstract class CallRedirectionService extends android.app.Service {
@@ -43828,6 +43765,7 @@
   }
 
   public final class PhoneAccountSuggestion implements android.os.Parcelable {
+    ctor public PhoneAccountSuggestion(@NonNull android.telecom.PhoneAccountHandle, int, boolean);
     method public int describeContents();
     method @NonNull public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
     method public int getReason();
@@ -43983,8 +43921,8 @@
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
     method public android.telecom.PhoneAccountHandle getSimCallManager();
-    method public String getSystemDialerPackage();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
+    method @Nullable public String getSystemDialerPackage();
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle);
@@ -44431,10 +44369,10 @@
   }
 
   public final class CellIdentityNr extends android.telephony.CellIdentity {
-    method public int getChannelNumber();
     method public String getMccString();
     method public String getMncString();
     method public long getNci();
+    method public int getNrarfcn();
     method public int getPci();
     method public int getTac();
     method public void writeToParcel(android.os.Parcel, int);
@@ -44782,6 +44720,7 @@
   public class PhoneStateListener {
     ctor public PhoneStateListener();
     ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
+    method public void onActiveDataSubscriptionIdChanged(int);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -44794,6 +44733,7 @@
     method @Deprecated public void onSignalStrengthChanged(int);
     method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
     method public void onUserMobileDataStateChanged(boolean);
+    field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
     field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
     field public static final int LISTEN_CALL_STATE = 32; // 0x20
     field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -44822,7 +44762,7 @@
   public class ServiceState implements android.os.Parcelable {
     ctor public ServiceState();
     ctor public ServiceState(android.telephony.ServiceState);
-    ctor public ServiceState(android.os.Parcel);
+    ctor @Deprecated public ServiceState(android.os.Parcel);
     method protected void copyFrom(android.telephony.ServiceState);
     method public int describeContents();
     method public int getCdmaNetworkId();
@@ -44859,7 +44799,7 @@
     method @Deprecated public int getCdmaDbm();
     method @Deprecated public int getCdmaEcio();
     method @NonNull public java.util.List<android.telephony.CellSignalStrength> getCellSignalStrengths();
-    method public <T extends android.telephony.CellSignalStrength> java.util.List<T> getCellSignalStrengths(@NonNull Class<T>);
+    method @NonNull public <T extends android.telephony.CellSignalStrength> java.util.List<T> getCellSignalStrengths(@NonNull Class<T>);
     method @Deprecated public int getEvdoDbm();
     method @Deprecated public int getEvdoEcio();
     method @Deprecated public int getEvdoSnr();
@@ -45145,8 +45085,8 @@
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei(int);
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number();
-    method public String getManufacturerCode();
-    method public String getManufacturerCode(int);
+    method @Nullable public String getManufacturerCode();
+    method @Nullable public String getManufacturerCode(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int);
     method public String getMmsUAProfUrl();
@@ -45173,8 +45113,8 @@
     method public int getSimState();
     method public int getSimState(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
-    method public String getTypeAllocationCode();
-    method public String getTypeAllocationCode(int);
+    method @Nullable public String getTypeAllocationCode();
+    method @Nullable public String getTypeAllocationCode(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
@@ -45215,7 +45155,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean);
     method public boolean setOperatorBrandOverride(String);
     method public boolean setPreferredNetworkTypeToGlobal();
-    method public boolean setPreferredOpportunisticDataSubscription(int);
+    method public void setPreferredOpportunisticDataSubscription(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
     method public boolean setVoiceMailNumber(String, String);
     method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
@@ -45470,6 +45410,7 @@
     field public static final int TYPE_HIPRI = 16; // 0x10
     field public static final int TYPE_IA = 256; // 0x100
     field public static final int TYPE_IMS = 64; // 0x40
+    field public static final int TYPE_MCX = 1024; // 0x400
     field public static final int TYPE_MMS = 2; // 0x2
     field public static final int TYPE_SUPL = 4; // 0x4
   }
@@ -45481,7 +45422,7 @@
     method public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
     method public android.telephony.data.ApnSetting.Builder setAuthType(int);
     method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
-    method public android.telephony.data.ApnSetting.Builder setCarrierId(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierId(int);
     method public android.telephony.data.ApnSetting.Builder setEntryName(String);
     method @Deprecated public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress);
     method public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String);
@@ -45559,7 +45500,7 @@
   }
 
   public class EuiccManager {
-    method public android.telephony.euicc.EuiccManager createForCardId(int);
+    method @NonNull public android.telephony.euicc.EuiccManager createForCardId(int);
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void deleteSubscription(int, android.app.PendingIntent);
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent);
     method @Nullable public String getEid();
@@ -47112,7 +47053,7 @@
 
   public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan android.text.ParcelableSpan {
     ctor public LineHeightSpan.Standard(@Px @IntRange(from=1) int);
-    ctor public LineHeightSpan.Standard(android.os.Parcel);
+    ctor public LineHeightSpan.Standard(@NonNull android.os.Parcel);
     method public void chooseHeight(@NonNull CharSequence, int, int, int, int, @NonNull android.graphics.Paint.FontMetricsInt);
     method public int describeContents();
     method @Px public int getHeight();
@@ -51972,6 +51913,7 @@
     method public int getStableInsetRight();
     method public int getStableInsetTop();
     method @NonNull public android.graphics.Insets getStableInsets();
+    method @NonNull public android.graphics.Insets getSystemGestureInsets();
     method public int getSystemWindowInsetBottom();
     method public int getSystemWindowInsetLeft();
     method public int getSystemWindowInsetRight();
@@ -51993,6 +51935,7 @@
     method @NonNull public android.view.WindowInsets build();
     method @NonNull public android.view.WindowInsets.Builder setDisplayCutout(@Nullable android.view.DisplayCutout);
     method @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets);
+    method @NonNull public android.view.WindowInsets.Builder setSystemGestureInsets(@NonNull android.graphics.Insets);
     method @NonNull public android.view.WindowInsets.Builder setSystemWindowInsets(@NonNull android.graphics.Insets);
   }
 
@@ -53036,7 +52979,7 @@
 
   public final class ContentCaptureContext implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull android.net.Uri);
+    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 public void writeToParcel(android.os.Parcel, int);
@@ -53084,18 +53027,19 @@
     method public boolean isForEverything();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR;
+    field public static final int FLAG_IS_PREFIX = 1; // 0x1
   }
 
   public static final class UserDataRemovalRequest.Builder {
     ctor public UserDataRemovalRequest.Builder();
-    method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, boolean);
+    method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
     method @NonNull public android.view.contentcapture.UserDataRemovalRequest build();
     method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
   }
 
   public final class UserDataRemovalRequest.LocusIdRequest {
+    method @NonNull public int getFlags();
     method @NonNull public android.content.LocusId getLocusId();
-    method @NonNull public boolean isRecursive();
   }
 
 }
@@ -53556,6 +53500,7 @@
     method public int mapIntFlag(@NonNull String, @AttrRes int, @NonNull android.view.inspector.IntFlagMapping);
     method public int mapLong(@NonNull String, @AttrRes int);
     method public int mapObject(@NonNull String, @AttrRes int);
+    method public int mapResourceId(@NonNull String, @AttrRes int);
     method public int mapShort(@NonNull String, @AttrRes int);
   }
 
@@ -53578,6 +53523,7 @@
     method public void readIntFlag(int, int);
     method public void readLong(int, long);
     method public void readObject(int, @Nullable Object);
+    method public void readResourceId(int, @AnyRes int);
     method public void readShort(int, short);
   }
 
@@ -56236,7 +56182,7 @@
     field public static final int SOURCE_BOUND_MAX_VISIBLE = 1; // 0x1
   }
 
-  public static class Magnifier.Builder {
+  public static final class Magnifier.Builder {
     ctor public Magnifier.Builder(@NonNull android.view.View);
     method @NonNull public android.widget.Magnifier build();
     method @NonNull public android.widget.Magnifier.Builder setClippingEnabled(boolean);
@@ -56785,7 +56731,7 @@
     method public boolean isFillViewport();
     method public boolean isSmoothScrollingEnabled();
     method public boolean pageScroll(int);
-    method public void scrollToDescendant(android.view.View);
+    method public void scrollToDescendant(@NonNull android.view.View);
     method public void setBottomEdgeEffectColor(@ColorInt int);
     method public void setEdgeEffectColor(@ColorInt int);
     method public void setFillViewport(boolean);
@@ -57331,7 +57277,7 @@
     method @NonNull public android.view.textclassifier.TextClassifier getTextClassifier();
     method public final android.content.res.ColorStateList getTextColors();
     method @Nullable public android.graphics.drawable.Drawable getTextCursorDrawable();
-    method public android.text.TextDirectionHeuristic getTextDirectionHeuristic();
+    method @NonNull public android.text.TextDirectionHeuristic getTextDirectionHeuristic();
     method @NonNull public java.util.Locale getTextLocale();
     method @NonNull @Size(min=1) public android.os.LocaleList getTextLocales();
     method @NonNull public android.text.PrecomputedText.Params getTextMetricsParams();
diff --git a/api/removed.txt b/api/removed.txt
index fdfaf91..93d06928 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -282,12 +282,38 @@
 
 package android.location {
 
+  @Deprecated public final class GpsStatus {
+    method public int getMaxSatellites();
+    method public Iterable<android.location.GpsSatellite> getSatellites();
+    method public int getTimeToFirstFix();
+    field public static final int GPS_EVENT_FIRST_FIX = 3; // 0x3
+    field public static final int GPS_EVENT_SATELLITE_STATUS = 4; // 0x4
+    field public static final int GPS_EVENT_STARTED = 1; // 0x1
+    field public static final int GPS_EVENT_STOPPED = 2; // 0x2
+  }
+
+  @Deprecated public static interface GpsStatus.Listener {
+    method public void onGpsStatusChanged(int);
+  }
+
+  @Deprecated public static interface GpsStatus.NmeaListener {
+    method public void onNmeaReceived(long, String);
+  }
+
   public class Location implements android.os.Parcelable {
     method @Deprecated public void removeBearingAccuracy();
     method @Deprecated public void removeSpeedAccuracy();
     method @Deprecated public void removeVerticalAccuracy();
   }
 
+  public class LocationManager {
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
+    method @Deprecated public void removeGpsStatusListener(android.location.GpsStatus.Listener);
+    method @Deprecated public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+  }
+
 }
 
 package android.media {
@@ -309,11 +335,17 @@
 package android.net {
 
   public class ConnectivityManager {
+    method @Deprecated public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
     method @Deprecated public boolean requestRouteToHost(int, int);
     method @Deprecated public int startUsingNetworkFeature(int, String);
     method @Deprecated public int stopUsingNetworkFeature(int, String);
   }
 
+  @Deprecated public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
+    ctor public ConnectivityManager.TetheringEntitlementValueListener();
+    method public void onEntitlementResult(int);
+  }
+
   @Deprecated public class NetworkBadging {
     method @NonNull public static android.graphics.drawable.Drawable getWifiIcon(@IntRange(from=0, to=4) int, int, @Nullable android.content.res.Resources.Theme);
     field public static final int BADGING_4K = 30; // 0x1e
diff --git a/api/system-current.txt b/api/system-current.txt
index 07fe64e..ced5259 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25,6 +25,7 @@
     field public static final String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE";
     field @Deprecated public static final String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE";
+    field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE";
     field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE";
     field public static final String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
@@ -121,6 +122,7 @@
     field public static final String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
     field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
     field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
+    field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
     field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
     field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
     field public static final String PACKET_KEEPALIVE_OFFLOAD = "android.permission.PACKET_KEEPALIVE_OFFLOAD";
@@ -159,9 +161,11 @@
     field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
     field public static final String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
+    field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
     field public static final String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
+    field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
     field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
     field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
@@ -180,6 +184,7 @@
     field public static final String SHUTDOWN = "android.permission.SHUTDOWN";
     field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
     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 TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
     field public static final String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
@@ -207,7 +212,6 @@
 
   public static final class R.attr {
     field public static final int allowClearUserDataOnFailedRestore = 16844198; // 0x10105a6
-    field public static final int inheritShowWhenLocked = 16844194; // 0x10105a2
     field public static final int isVrOnly = 16844152; // 0x1010578
     field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
     field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
@@ -277,7 +281,6 @@
     method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions);
     method @Deprecated public boolean isBackgroundVisibleBehind();
     method @Deprecated public void onBackgroundVisibleBehindChanged(boolean);
-    method public void setInheritShowWhenLocked(boolean);
   }
 
   public static interface Activity.TranslucentConversionListener {
@@ -361,27 +364,34 @@
     field public static final String OPSTR_WRITE_ICC_SMS = "android:write_icc_sms";
     field public static final String OPSTR_WRITE_SMS = "android:write_sms";
     field public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
-    field public static final int UID_STATE_BACKGROUND = 5; // 0x5
-    field public static final int UID_STATE_CACHED = 6; // 0x6
-    field public static final int UID_STATE_FOREGROUND = 4; // 0x4
-    field public static final int UID_STATE_FOREGROUND_SERVICE = 3; // 0x3
-    field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 2; // 0x2
-    field public static final int UID_STATE_PERSISTENT = 0; // 0x0
-    field public static final int UID_STATE_TOP = 1; // 0x1
+    field public static final int OP_FLAGS_ALL = 31; // 0x1f
+    field public static final int OP_FLAGS_ALL_TRUSTED = 13; // 0xd
+    field public static final int OP_FLAG_SELF = 1; // 0x1
+    field public static final int OP_FLAG_TRUSTED_PROXIED = 8; // 0x8
+    field public static final int OP_FLAG_TRUSTED_PROXY = 2; // 0x2
+    field public static final int OP_FLAG_UNTRUSTED_PROXIED = 16; // 0x10
+    field public static final int OP_FLAG_UNTRUSTED_PROXY = 4; // 0x4
+    field public static final int UID_STATE_BACKGROUND = 600; // 0x258
+    field public static final int UID_STATE_CACHED = 700; // 0x2bc
+    field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
+    field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
+    field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
+    field public static final int UID_STATE_PERSISTENT = 100; // 0x64
+    field public static final int UID_STATE_TOP = 200; // 0xc8
   }
 
   public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
     method public int describeContents();
-    method public long getAccessCount(int);
-    method public long getAccessDuration(int);
-    method public long getBackgroundAccessCount();
-    method public long getBackgroundAccessDuration();
-    method public long getBackgroundRejectCount();
-    method public long getForegroundAccessCount();
-    method public long getForegroundAccessDuration();
-    method public long getForegroundRejectCount();
+    method public long getAccessCount(int, int, int);
+    method public long getAccessDuration(int, int, int);
+    method public long getBackgroundAccessCount(int);
+    method public long getBackgroundAccessDuration(int);
+    method public long getBackgroundRejectCount(int);
+    method public long getForegroundAccessCount(int);
+    method public long getForegroundAccessDuration(int);
+    method public long getForegroundRejectCount(int);
     method @NonNull public String getOpName();
-    method public long getRejectCount(int);
+    method public long getRejectCount(int, int, int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOp> CREATOR;
   }
@@ -403,6 +413,7 @@
   public static final class AppOpsManager.HistoricalOpsRequest.Builder {
     ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
+    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
@@ -430,17 +441,24 @@
 
   public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
     method public int describeContents();
-    method public int getDuration();
-    method public long getLastAccessBackgroundTime();
-    method public long getLastAccessForegroundTime();
-    method public long getLastAccessTime();
-    method public long getLastRejectBackgroundTime();
-    method public long getLastRejectForegroundTime();
-    method public long getLastRejectTime();
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
     method public int getMode();
-    method public String getOpStr();
-    method public String getProxyPackageName();
+    method @NonNull public String getOpStr();
+    method @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
     method public int getProxyUid();
+    method public int getProxyUid(int, int);
     method public boolean isRunning();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
@@ -449,7 +467,7 @@
   public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
     method public int describeContents();
     method public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
-    method public String getPackageName();
+    method @NonNull public String getPackageName();
     method public int getUid();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.PackageOps> CREATOR;
@@ -457,7 +475,7 @@
 
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
-    method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setAllowBackgroundActivityStarts(boolean);
+    method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
     method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
     method public android.os.Bundle toBundle();
@@ -530,6 +548,7 @@
   public class NotificationManager {
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
     method @Nullable public android.content.ComponentName getAllowedNotificationAssistantForUser(android.os.UserHandle);
+    method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
     method public void setNotificationAssistantAccessGranted(android.content.ComponentName, boolean);
     method public void setNotificationAssistantAccessGrantedForUser(android.content.ComponentName, android.os.UserHandle, boolean);
   }
@@ -935,7 +954,7 @@
 
   public final class ClassificationsRequest implements android.os.Parcelable {
     method public int describeContents();
-    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public android.os.Bundle getExtras();
     method @NonNull public java.util.List<android.app.contentsuggestions.ContentSelection> getSelections();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.contentsuggestions.ClassificationsRequest> CREATOR;
@@ -943,8 +962,8 @@
 
   public static final class ClassificationsRequest.Builder {
     ctor public ClassificationsRequest.Builder(@NonNull java.util.List<android.app.contentsuggestions.ContentSelection>);
-    method public android.app.contentsuggestions.ClassificationsRequest build();
-    method public android.app.contentsuggestions.ClassificationsRequest.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.app.contentsuggestions.ClassificationsRequest build();
+    method @NonNull public android.app.contentsuggestions.ClassificationsRequest.Builder setExtras(@NonNull android.os.Bundle);
   }
 
   public final class ContentClassification implements android.os.Parcelable {
@@ -982,7 +1001,7 @@
 
   public final class SelectionsRequest implements android.os.Parcelable {
     method public int describeContents();
-    method @Nullable public android.os.Bundle getExtras();
+    method @NonNull public android.os.Bundle getExtras();
     method @Nullable public android.graphics.Point getInterestPoint();
     method public int getTaskId();
     method public void writeToParcel(android.os.Parcel, int);
@@ -991,9 +1010,9 @@
 
   public static final class SelectionsRequest.Builder {
     ctor public SelectionsRequest.Builder(int);
-    method public android.app.contentsuggestions.SelectionsRequest build();
-    method public android.app.contentsuggestions.SelectionsRequest.Builder setExtras(@NonNull android.os.Bundle);
-    method public android.app.contentsuggestions.SelectionsRequest.Builder setInterestPoint(@NonNull android.graphics.Point);
+    method @NonNull public android.app.contentsuggestions.SelectionsRequest build();
+    method @NonNull public android.app.contentsuggestions.SelectionsRequest.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.app.contentsuggestions.SelectionsRequest.Builder setInterestPoint(@NonNull android.graphics.Point);
   }
 
 }
@@ -1171,7 +1190,7 @@
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String);
     method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets();
     method public int getUsageSource();
-    method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @Nullable android.app.PendingIntent);
+    method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent);
     method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String);
@@ -1396,7 +1415,7 @@
     field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
     field public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
-    field public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
+    field @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES) public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
     field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_APP_PERMISSION_USAGE = "android.intent.action.REVIEW_APP_PERMISSION_USAGE";
     field public static final String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
     field public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
@@ -1690,9 +1709,9 @@
   }
 
   public class PermissionGroupInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
-    field @StringRes public int backgroundRequestDetailResourceId;
-    field @StringRes public int backgroundRequestResourceId;
-    field @StringRes public int requestDetailResourceId;
+    field @StringRes public final int backgroundRequestDetailResourceId;
+    field @StringRes public final int backgroundRequestResourceId;
+    field @StringRes public final int requestDetailResourceId;
     field @StringRes public int requestRes;
   }
 
@@ -1705,8 +1724,8 @@
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
-    field public String backgroundPermission;
-    field public int requestRes;
+    field @Nullable public final String backgroundPermission;
+    field @StringRes public int requestRes;
   }
 
   public class ResolveInfo implements android.os.Parcelable {
@@ -3039,81 +3058,75 @@
 
   public final class GnssMeasurementCorrections implements android.os.Parcelable {
     method public int describeContents();
-    method public double getAltitudeMeters();
-    method public double getHorizontalPositionUncertaintyMeters();
-    method public double getLatitudeDegrees();
-    method public double getLongitudeDegrees();
-    method @Nullable public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
-    method public long getToaGpsNanosecondsOfWeek();
-    method public double getVerticalPositionUncertaintyMeters();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
+    method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+    method @FloatRange(from=0.0f) public double getHorizontalPositionUncertaintyMeters();
+    method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+    method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+    method @NonNull public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
+    method @IntRange(from=0) public long getToaGpsNanosecondsOfWeek();
+    method @FloatRange(from=0.0f) public double getVerticalPositionUncertaintyMeters();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
   }
 
   public static final class GnssMeasurementCorrections.Builder {
     ctor public GnssMeasurementCorrections.Builder();
-    method public android.location.GnssMeasurementCorrections build();
-    method public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(double);
-    method public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(double);
-    method public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(double);
-    method public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(double);
-    method public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@Nullable java.util.List<android.location.GnssSingleSatCorrection>);
-    method public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(long);
-    method public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(double);
+    method @NonNull public android.location.GnssMeasurementCorrections build();
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@NonNull java.util.List<android.location.GnssSingleSatCorrection>);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(@IntRange(from=0) long);
+    method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
   }
 
   public final class GnssReflectingPlane implements android.os.Parcelable {
     method public int describeContents();
-    method public double getAltitudeMeters();
-    method public double getAzimuthDegrees();
-    method public double getLatitudeDegrees();
-    method public double getLongitudeDegrees();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
+    method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
+    method @FloatRange(from=0.0f, to=360.0f) public double getAzimuthDegrees();
+    method @FloatRange(from=-90.0F, to=90.0f) public double getLatitudeDegrees();
+    method @FloatRange(from=-180.0F, to=180.0f) public double getLongitudeDegrees();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
   }
 
   public static final class GnssReflectingPlane.Builder {
     ctor public GnssReflectingPlane.Builder();
-    method public android.location.GnssReflectingPlane build();
-    method public android.location.GnssReflectingPlane.Builder setAltitudeMeters(double);
-    method public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(double);
-    method public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(double);
-    method public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(double);
+    method @NonNull public android.location.GnssReflectingPlane build();
+    method @NonNull public android.location.GnssReflectingPlane.Builder setAltitudeMeters(@FloatRange(from=-1000.0F, to=10000.0f) double);
+    method @NonNull public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(@FloatRange(from=0.0f, to=360.0f) double);
+    method @NonNull public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(@FloatRange(from=-90.0F, to=90.0f) double);
+    method @NonNull public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(@FloatRange(from=-180.0F, to=180.0f) double);
   }
 
   public final class GnssSingleSatCorrection implements android.os.Parcelable {
     method public int describeContents();
-    method public float getCarrierFrequencyHz();
+    method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
     method public int getConstellationType();
-    method public float getExcessPathLengthMeters();
-    method public float getExcessPathLengthUncertaintyMeters();
+    method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+    method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
     method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
     method @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
-    method public int getSatelliteId();
-    method public int getSingleSatelliteCorrectionFlags();
+    method @IntRange(from=0) public int getSatelliteId();
     method public boolean hasExcessPathLength();
     method public boolean hasExcessPathLengthUncertainty();
     method public boolean hasReflectingPlane();
     method public boolean hasValidSatelliteLineOfSight();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
-    field public static final int HAS_EXCESS_PATH_LENGTH_MASK = 2; // 0x2
-    field public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 4; // 0x4
-    field public static final int HAS_PROB_SAT_IS_LOS_MASK = 1; // 0x1
-    field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
   }
 
   public static final class GnssSingleSatCorrection.Builder {
     ctor public GnssSingleSatCorrection.Builder();
-    method public android.location.GnssSingleSatCorrection build();
-    method public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(float);
-    method public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
-    method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(float);
-    method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(float);
-    method public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
-    method public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(android.location.GnssReflectingPlane);
-    method public android.location.GnssSingleSatCorrection.Builder setSatelliteId(int);
-    method public android.location.GnssSingleSatCorrection.Builder setSingleSatelliteCorrectionFlags(int);
+    method @NonNull public android.location.GnssSingleSatCorrection build();
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
   }
 
   public class GpsClock implements android.os.Parcelable {
@@ -3348,57 +3361,53 @@
   }
 
   public class LocationManager {
-    method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
-    method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
     method public int getGnssCapabilities();
     method @Nullable public String getLocationControllerExtraPackage();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isLocationControllerExtraPackageEnabled();
-    method public boolean isLocationEnabledForUser(android.os.UserHandle);
-    method public boolean isProviderEnabledForUser(String, android.os.UserHandle);
-    method public boolean isProviderPackage(String);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, android.location.BatchedLocationCallback, android.os.Handler);
-    method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
-    method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(String);
+    method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
+    method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
+    method public boolean isProviderPackage(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackage(@NonNull String);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setLocationControllerExtraPackageEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, android.os.UserHandle);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(String, boolean, android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(android.location.BatchedLocationCallback);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
+    method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
   }
 
   public final class LocationRequest implements android.os.Parcelable {
-    method public static android.location.LocationRequest create();
-    method public static android.location.LocationRequest createFromDeprecatedCriteria(android.location.Criteria, long, float, boolean);
-    method public static android.location.LocationRequest createFromDeprecatedProvider(String, long, float, boolean);
+    method @NonNull public static android.location.LocationRequest create();
+    method @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
+    method @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
     method public int describeContents();
     method public long getExpireAt();
     method public long getFastestInterval();
     method public boolean getHideFromAppOps();
     method public long getInterval();
     method public int getNumUpdates();
-    method public String getProvider();
+    method @NonNull public String getProvider();
     method public int getQuality();
     method public float getSmallestDisplacement();
-    method public android.os.WorkSource getWorkSource();
+    method @Nullable public android.os.WorkSource getWorkSource();
     method public boolean isLocationSettingsIgnored();
     method public boolean isLowPowerMode();
-    method public android.location.LocationRequest setExpireAt(long);
-    method public android.location.LocationRequest setExpireIn(long);
-    method public android.location.LocationRequest setFastestInterval(long);
+    method @NonNull public android.location.LocationRequest setExpireAt(long);
+    method @NonNull public android.location.LocationRequest setExpireIn(long);
+    method @NonNull public android.location.LocationRequest setFastestInterval(long);
     method public void setHideFromAppOps(boolean);
-    method public android.location.LocationRequest setInterval(long);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
-    method public android.location.LocationRequest setLowPowerMode(boolean);
-    method public android.location.LocationRequest setNumUpdates(int);
-    method public android.location.LocationRequest setProvider(String);
-    method public android.location.LocationRequest setQuality(int);
-    method public android.location.LocationRequest setSmallestDisplacement(float);
-    method public void setWorkSource(android.os.WorkSource);
+    method @NonNull public android.location.LocationRequest setInterval(long);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+    method @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
+    method @NonNull public android.location.LocationRequest setNumUpdates(int);
+    method @NonNull public android.location.LocationRequest setProvider(@NonNull String);
+    method @NonNull public android.location.LocationRequest setQuality(int);
+    method @NonNull public android.location.LocationRequest setSmallestDisplacement(float);
+    method public void setWorkSource(@Nullable android.os.WorkSource);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACCURACY_BLOCK = 102; // 0x66
     field public static final int ACCURACY_CITY = 104; // 0x68
@@ -3520,11 +3529,12 @@
   }
 
   public class HwAudioSource {
+    method public boolean isPlaying();
     method public void start();
     method public void stop();
   }
 
-  public static class HwAudioSource.Builder {
+  public static final class HwAudioSource.Builder {
     ctor public HwAudioSource.Builder();
     method @NonNull public android.media.HwAudioSource build();
     method @NonNull public android.media.HwAudioSource.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
@@ -3537,7 +3547,7 @@
     field public static final int RADIO_TUNER = 1998; // 0x7ce
   }
 
-  public static class MediaTimestamp.Builder {
+  public static final class MediaTimestamp.Builder {
     ctor public MediaTimestamp.Builder();
     ctor public MediaTimestamp.Builder(@NonNull android.media.MediaTimestamp);
     method @NonNull public android.media.MediaTimestamp build();
@@ -3553,14 +3563,14 @@
     method public void stop();
   }
 
-  public static class SubtitleData.Builder {
+  public static final class SubtitleData.Builder {
     ctor public SubtitleData.Builder();
     ctor public SubtitleData.Builder(@NonNull android.media.SubtitleData);
     method @NonNull public android.media.SubtitleData build();
     method @NonNull public android.media.SubtitleData.Builder setSubtitleData(int, long, long, @NonNull byte[]);
   }
 
-  public static class TimedMetaData.Builder {
+  public static final class TimedMetaData.Builder {
     ctor public TimedMetaData.Builder();
     ctor public TimedMetaData.Builder(@NonNull android.media.TimedMetaData);
     method @NonNull public android.media.TimedMetaData build();
@@ -3662,7 +3672,7 @@
     method @Nullable public android.media.audiopolicy.AudioProductStrategy getProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes);
     method public int getVolumeGroupIdForAttributes(@NonNull android.media.AudioAttributes);
     method public int getVolumeGroupIdForLegacyStreamType(int);
-    method public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
+    method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
     method public int size();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategies> CREATOR;
@@ -3679,7 +3689,7 @@
 
   public final class AudioVolumeGroup implements android.os.Parcelable {
     method public int describeContents();
-    method public java.util.List<android.media.AudioAttributes> getAudioAttributes();
+    method @NonNull public java.util.List<android.media.AudioAttributes> getAudioAttributes();
     method public int getId();
     method @NonNull public int[] getLegacyStreamTypes();
     method @NonNull public String name();
@@ -3691,7 +3701,7 @@
     ctor public AudioVolumeGroups();
     method public int describeContents();
     method @Nullable public android.media.audiopolicy.AudioVolumeGroup getById(int);
-    method public java.util.Iterator<android.media.audiopolicy.AudioVolumeGroup> iterator();
+    method @NonNull public java.util.Iterator<android.media.audiopolicy.AudioVolumeGroup> iterator();
     method public int size();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioVolumeGroups> CREATOR;
@@ -4024,7 +4034,7 @@
     method @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method public boolean getAvoidBadWifi();
     method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) public String getCaptivePortalServerUrl();
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementValue(int, boolean, @NonNull android.net.ConnectivityManager.TetheringEntitlementValueListener, @Nullable android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, android.os.Bundle);
@@ -4047,8 +4057,7 @@
     method public void onTetheringStarted();
   }
 
-  public abstract static class ConnectivityManager.TetheringEntitlementValueListener {
-    ctor public ConnectivityManager.TetheringEntitlementValueListener();
+  public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
     method public void onEntitlementResult(int);
   }
 
@@ -4458,19 +4467,16 @@
 package android.net.util {
 
   public class SocketUtils {
-    method public static void addArpEntry(java.net.Inet4Address, android.net.MacAddress, String, java.io.FileDescriptor) throws java.io.IOException;
-    method public static void attachControlPacketFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
-    method public static void attachDhcpFilter(java.io.FileDescriptor) throws java.net.SocketException;
-    method public static void attachRaFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
-    method public static void bindSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
-    method public static void bindSocketToInterface(java.io.FileDescriptor, String) throws android.system.ErrnoException;
-    method public static void closeSocket(java.io.FileDescriptor) throws java.io.IOException;
-    method public static void connectSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void addArpEntry(@NonNull java.net.Inet4Address, @NonNull android.net.MacAddress, @NonNull String, @NonNull java.io.FileDescriptor) throws java.io.IOException;
+    method public static void attachControlPacketFilter(@NonNull java.io.FileDescriptor, int) throws java.net.SocketException;
+    method public static void attachDhcpFilter(@NonNull java.io.FileDescriptor) throws java.net.SocketException;
+    method public static void attachRaFilter(@NonNull java.io.FileDescriptor, int) throws java.net.SocketException;
+    method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
+    method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
     method public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
     method public static java.net.SocketAddress makePacketSocketAddress(short, int);
-    method public static java.net.SocketAddress makePacketSocketAddress(int, byte[]);
-    method public static void sendTo(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
-    method public static void setSocketTimeValueOption(java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
+    method public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+    method public static void setSocketTimeValueOption(@NonNull java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
   }
 
 }
@@ -4738,7 +4744,7 @@
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.ProvisioningCallback, @Nullable android.os.Handler);
+    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
     method @RequiresPermission("android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE") public void updateWifiUsabilityScore(int, int, int);
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
@@ -4951,7 +4957,7 @@
     method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
   }
 
-  public static class WifiAwareManager.NetworkSpecifierBuilder {
+  public static final class WifiAwareManager.NetworkSpecifierBuilder {
     method @NonNull public android.net.wifi.aware.WifiAwareManager.NetworkSpecifierBuilder setPmk(@NonNull byte[]);
   }
 
@@ -5268,7 +5274,7 @@
     method public final void putInt64Array(long, long[]);
     method public final void putInt8(long, byte);
     method public final void putInt8Array(long, byte[]);
-    method public final void putNativeHandle(long, android.os.NativeHandle);
+    method public final void putNativeHandle(long, @Nullable android.os.NativeHandle);
     method public final void putString(long, String);
     method public static Boolean[] wrapArray(@NonNull boolean[]);
     method public static Long[] wrapArray(@NonNull long[]);
@@ -5288,7 +5294,7 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
-    method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
+    method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
     method public final short readInt16();
@@ -5299,8 +5305,8 @@
     method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
     method public final byte readInt8();
     method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
-    method public final android.os.NativeHandle readNativeHandle();
-    method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
+    method @Nullable public final android.os.NativeHandle readNativeHandle();
+    method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -5324,8 +5330,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(String);
-    method public final void writeNativeHandle(android.os.NativeHandle);
-    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
+    method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
+    method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -5417,10 +5423,10 @@
     ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
     ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull int[], boolean);
     method public void close() throws java.io.IOException;
-    method public android.os.NativeHandle dup() throws java.io.IOException;
-    method public java.io.FileDescriptor getFileDescriptor();
-    method public java.io.FileDescriptor[] getFileDescriptors();
-    method public int[] getInts();
+    method @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
+    method @NonNull public java.io.FileDescriptor getFileDescriptor();
+    method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
+    method @NonNull public int[] getInts();
     method public boolean hasSingleFileDescriptor();
   }
 
@@ -5574,9 +5580,9 @@
     method public boolean isSystem();
     method public static int myUserId();
     method public static android.os.UserHandle of(int);
-    field public static final android.os.UserHandle ALL;
-    field public static final android.os.UserHandle CURRENT;
-    field public static final android.os.UserHandle SYSTEM;
+    field @NonNull public static final android.os.UserHandle ALL;
+    field @NonNull public static final android.os.UserHandle CURRENT;
+    field @NonNull public static final android.os.UserHandle SYSTEM;
   }
 
   public class UserManager {
@@ -5587,7 +5593,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
     method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
     method public boolean hasRestrictedProfiles();
@@ -5598,8 +5604,8 @@
     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 removeUser(android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(android.graphics.Bitmap);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(String);
+    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);
     field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
     field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
     field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -5672,6 +5678,7 @@
     method @NonNull public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onGetPermissionUsages(boolean, long);
     method public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream);
     method public abstract boolean onIsApplicationQualifiedForRole(@NonNull String, @NonNull String);
+    method public abstract boolean onIsRoleVisible(@NonNull String);
     method @BinderThread public abstract boolean onRestoreDelayedRuntimePermissionsBackup(@NonNull String, @NonNull android.os.UserHandle);
     method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream);
     method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String);
@@ -5691,7 +5698,7 @@
   }
 
   public final class RuntimePermissionPresentationInfo implements android.os.Parcelable {
-    ctor public RuntimePermissionPresentationInfo(CharSequence, boolean, boolean);
+    ctor public RuntimePermissionPresentationInfo(@NonNull CharSequence, boolean, boolean);
     method public int describeContents();
     method @NonNull public CharSequence getLabel();
     method public boolean isGranted();
@@ -5835,17 +5842,17 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(String, String, String, boolean);
     field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
+    field public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT = "activity_manager_native_boot";
     field public static final String NAMESPACE_AUTOFILL = "autofill";
+    field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
     field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
     field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
+    field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+    field public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot";
     field public static final String NAMESPACE_SYSTEMUI = "systemui";
-  }
-
-  public static interface DeviceConfig.ActivityManagerNativeBoot {
-    field public static final String NAMESPACE = "activity_manager_native_boot";
-    field public static final String OFFLOAD_QUEUE_ENABLED = "offload_queue_enabled";
+    field public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
   }
 
   public static interface DeviceConfig.AttentionManagerService {
@@ -5866,11 +5873,8 @@
     field public static final String NAMESPACE = "intelligence_attention";
   }
 
-  public static interface DeviceConfig.MediaNative {
-    field public static final String NAMESPACE = "media_native";
-  }
-
   public static interface DeviceConfig.OnPropertyChangedListener {
+    method public default void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
     method public void onPropertyChanged(String, String, String);
   }
 
@@ -5880,6 +5884,16 @@
     field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
   }
 
+  public static class DeviceConfig.Properties {
+    method public boolean getBoolean(@NonNull String, boolean);
+    method public float getFloat(@NonNull String, float);
+    method public int getInt(@NonNull String, int);
+    method @NonNull public java.util.Set<java.lang.String> getKeyset();
+    method public long getLong(@NonNull String, long);
+    method @NonNull public String getNamespace();
+    method @Nullable public String getString(@NonNull String, @Nullable String);
+  }
+
   public static interface DeviceConfig.Rollback {
     field public static final String BOOT_NAMESPACE = "rollback_boot";
     field public static final String ENABLE_ROLLBACK_TIMEOUT = "enable_rollback_timeout";
@@ -5896,10 +5910,6 @@
     field public static final String NAMESPACE = "runtime_native";
   }
 
-  public static interface DeviceConfig.RuntimeNativeBoot {
-    field public static final String NAMESPACE = "runtime_native_boot";
-  }
-
   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";
@@ -5918,8 +5928,8 @@
   }
 
   public final class DocumentsContract {
-    method public static boolean isManageMode(android.net.Uri);
-    method public static android.net.Uri setManageMode(android.net.Uri);
+    method public static boolean isManageMode(@NonNull android.net.Uri);
+    method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri);
     field public static final String ACTION_DOCUMENT_ROOT_SETTINGS = "android.provider.action.DOCUMENT_ROOT_SETTINGS";
     field public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
     field public static final String EXTRA_SHOW_ADVANCED = "android.provider.extra.SHOW_ADVANCED";
@@ -6044,6 +6054,7 @@
   }
 
   public final class Settings {
+    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_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
@@ -6070,6 +6081,7 @@
     field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
     field public static final String DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = "data_stall_consecutive_dns_timeout_threshold";
     field public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
+    field public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1; // 0x1
     field public static final String DATA_STALL_MIN_EVALUATE_INTERVAL = "data_stall_min_evaluate_interval";
     field public static final String DATA_STALL_VALID_DNS_TIME_THRESHOLD = "data_stall_valid_dns_time_threshold";
     field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
@@ -6178,8 +6190,8 @@
   }
 
   public class DeviceIdAttestationException extends java.lang.Exception {
-    ctor public DeviceIdAttestationException(String);
-    ctor public DeviceIdAttestationException(String, Throwable);
+    ctor public DeviceIdAttestationException(@Nullable String);
+    ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
   }
 
 }
@@ -6213,10 +6225,10 @@
   public static class KeyChainProtectionParams.Builder {
     ctor public KeyChainProtectionParams.Builder();
     method @NonNull public android.security.keystore.recovery.KeyChainProtectionParams build();
-    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setKeyDerivationParams(@NonNull android.security.keystore.recovery.KeyDerivationParams);
-    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setLockScreenUiFormat(int);
-    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setSecret(@NonNull byte[]);
-    method public android.security.keystore.recovery.KeyChainProtectionParams.Builder setUserSecretType(int);
+    method @NonNull public android.security.keystore.recovery.KeyChainProtectionParams.Builder setKeyDerivationParams(@NonNull android.security.keystore.recovery.KeyDerivationParams);
+    method @NonNull public android.security.keystore.recovery.KeyChainProtectionParams.Builder setLockScreenUiFormat(int);
+    method @NonNull public android.security.keystore.recovery.KeyChainProtectionParams.Builder setSecret(@NonNull byte[]);
+    method @NonNull public android.security.keystore.recovery.KeyChainProtectionParams.Builder setUserSecretType(int);
   }
 
   public final class KeyChainSnapshot implements android.os.Parcelable {
@@ -6297,9 +6309,9 @@
   public static class WrappedApplicationKey.Builder {
     ctor public WrappedApplicationKey.Builder();
     method @NonNull public android.security.keystore.recovery.WrappedApplicationKey build();
-    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(@NonNull String);
-    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(@NonNull byte[]);
-    method public android.security.keystore.recovery.WrappedApplicationKey.Builder setMetadata(@Nullable byte[]);
+    method @NonNull public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(@NonNull String);
+    method @NonNull public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(@NonNull byte[]);
+    method @NonNull public android.security.keystore.recovery.WrappedApplicationKey.Builder setMetadata(@Nullable byte[]);
   }
 
 }
@@ -6416,8 +6428,8 @@
 
   public abstract class ApnService extends android.app.Service {
     ctor public ApnService();
-    method public android.os.IBinder onBind(android.content.Intent);
-    method @WorkerThread public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
+    method @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent);
+    method @WorkerThread @NonNull public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
   }
 
 }
@@ -6608,13 +6620,78 @@
 
   public final class Adjustment implements android.os.Parcelable {
     ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
+    ctor public Adjustment(@NonNull String, @NonNull String, @NonNull android.os.Bundle, @NonNull CharSequence, @NonNull android.os.UserHandle);
     ctor protected Adjustment(android.os.Parcel);
+    method public int describeContents();
+    method @NonNull public CharSequence getExplanation();
+    method @NonNull public String getKey();
+    method @NonNull public String getPackage();
+    method @NonNull public android.os.Bundle getSignals();
     method public int getUser();
+    method @NonNull public android.os.UserHandle getUserHandle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+    field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
+    field public static final String KEY_IMPORTANCE = "key_importance";
     field public static final String KEY_PEOPLE = "key_people";
+    field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+    field public static final String KEY_TEXT_REPLIES = "key_text_replies";
+    field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
+  }
+
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustNotification(@NonNull android.service.notification.Adjustment);
+    method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>);
+    method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int);
+    method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent);
+    method public void onNotificationDirectReplied(@NonNull String);
+    method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification);
+    method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
+    method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
+    method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
+    method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
+    method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
+    method public final void unsnoozeNotification(@NonNull String);
+    field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
+    field public static final int SOURCE_FROM_APP = 0; // 0x0
+    field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
+  }
+
+  public abstract class NotificationListenerService extends android.app.Service {
+    method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
   }
 
   public final class NotificationStats implements android.os.Parcelable {
+    ctor public NotificationStats();
     ctor protected NotificationStats(android.os.Parcel);
+    method public int describeContents();
+    method public int getDismissalSentiment();
+    method public int getDismissalSurface();
+    method public boolean hasDirectReplied();
+    method public boolean hasExpanded();
+    method public boolean hasInteracted();
+    method public boolean hasSeen();
+    method public boolean hasSnoozed();
+    method public boolean hasViewedSettings();
+    method public void setDirectReplied();
+    method public void setDismissalSentiment(int);
+    method public void setDismissalSurface(int);
+    method public void setExpanded();
+    method public void setSeen();
+    method public void setSnoozed();
+    method public void setViewedSettings();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
+    field public static final int DISMISSAL_AOD = 2; // 0x2
+    field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
+    field public static final int DISMISSAL_OTHER = 0; // 0x0
+    field public static final int DISMISSAL_PEEK = 1; // 0x1
+    field public static final int DISMISSAL_SHADE = 3; // 0x3
+    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
   }
 
   public final class SnoozeCriterion implements android.os.Parcelable {
@@ -6754,15 +6831,15 @@
     method public static android.view.textclassifier.TextClassifier getDefaultTextClassifierImplementation(@NonNull android.content.Context);
     method @Deprecated public final android.view.textclassifier.TextClassifier getLocalTextClassifier();
     method @Nullable public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract void onClassifyText(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassification.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
-    method public void onCreateTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationContext, @NonNull android.view.textclassifier.TextClassificationSessionId);
-    method public void onDestroyTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationSessionId);
-    method public void onDetectLanguage(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLanguage.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLanguage>);
-    method public abstract void onGenerateLinks(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLinks.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
-    method @Deprecated public void onSelectionEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.SelectionEvent);
-    method public void onSuggestConversationActions(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.ConversationActions.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.ConversationActions>);
-    method public abstract void onSuggestSelection(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextSelection.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
-    method public void onTextClassifierEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassifierEvent);
+    method @MainThread public abstract void onClassifyText(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassification.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextClassification>);
+    method @MainThread public void onCreateTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationContext, @NonNull android.view.textclassifier.TextClassificationSessionId);
+    method @MainThread public void onDestroyTextClassificationSession(@NonNull android.view.textclassifier.TextClassificationSessionId);
+    method @MainThread public void onDetectLanguage(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLanguage.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLanguage>);
+    method @MainThread public abstract void onGenerateLinks(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextLinks.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextLinks>);
+    method @Deprecated @MainThread public void onSelectionEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.SelectionEvent);
+    method @MainThread public void onSuggestConversationActions(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.ConversationActions.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.ConversationActions>);
+    method @MainThread public abstract void onSuggestSelection(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextSelection.Request, @NonNull android.os.CancellationSignal, @NonNull android.service.textclassifier.TextClassifierService.Callback<android.view.textclassifier.TextSelection>);
+    method @MainThread public void onTextClassifierEvent(@Nullable android.view.textclassifier.TextClassificationSessionId, @NonNull android.view.textclassifier.TextClassifierEvent);
     field public static final String SERVICE_INTERFACE = "android.service.textclassifier.TextClassifierService";
   }
 
@@ -6989,10 +7066,6 @@
     field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
   }
 
-  public final class PhoneAccountSuggestion implements android.os.Parcelable {
-    ctor public PhoneAccountSuggestion(@NonNull android.telecom.PhoneAccountHandle, int, boolean);
-  }
-
   public class PhoneAccountSuggestionService extends android.app.Service {
     ctor public PhoneAccountSuggestionService();
     method public void onAccountSuggestionRequest(@NonNull String);
@@ -7068,8 +7141,8 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.WRITE_SECURE_SETTINGS}) public boolean setDefaultDialer(String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(android.telecom.PhoneAccountHandle);
+    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.WRITE_SECURE_SETTINGS}) public boolean setDefaultDialer(@Nullable String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
     field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
     field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
@@ -7089,12 +7162,12 @@
     field public static final int WWAN = 1; // 0x1
   }
 
-  public class CallAttributes implements android.os.Parcelable {
-    ctor public CallAttributes(android.telephony.PreciseCallState, int, android.telephony.CallQuality);
+  public final class CallAttributes implements android.os.Parcelable {
+    ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
     method public int describeContents();
-    method public android.telephony.CallQuality getCallQuality();
+    method @NonNull public android.telephony.CallQuality getCallQuality();
     method public int getNetworkType();
-    method public android.telephony.PreciseCallState getPreciseCallState();
+    method @NonNull public android.telephony.PreciseCallState getPreciseCallState();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
   }
@@ -7131,13 +7204,13 @@
   }
 
   public final class CarrierRestrictionRules implements android.os.Parcelable {
+    method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
     method public int describeContents();
     method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers();
     method public int getDefaultCarrierRestriction();
     method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
     method public int getMultiSimPolicy();
     method public boolean isAllCarriersAllowed();
-    method public java.util.List<java.lang.Boolean> isCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1
     field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0
@@ -7146,13 +7219,13 @@
     field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1
   }
 
-  public static class CarrierRestrictionRules.Builder {
-    method public android.telephony.CarrierRestrictionRules build();
-    method public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed();
-    method public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>);
-    method public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int);
-    method public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>);
-    method public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
+  public static final class CarrierRestrictionRules.Builder {
+    method @NonNull public android.telephony.CarrierRestrictionRules build();
+    method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed();
+    method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
+    method @NonNull public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int);
+    method @NonNull public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
+    method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
   }
 
   public final class DataFailCause {
@@ -7607,12 +7680,11 @@
   }
 
   public class NetworkRegistrationState implements android.os.Parcelable {
-    ctor public NetworkRegistrationState(int, int, int, int, int, boolean, int[], @Nullable android.telephony.CellIdentity);
-    ctor protected NetworkRegistrationState(android.os.Parcel);
+    ctor public NetworkRegistrationState(int, int, int, int, int, boolean, @NonNull int[], @Nullable android.telephony.CellIdentity);
     method public int describeContents();
     method public int getAccessNetworkTechnology();
-    method public int[] getAvailableServices();
-    method public android.telephony.CellIdentity getCellIdentity();
+    method @NonNull public int[] getAvailableServices();
+    method @Nullable public android.telephony.CellIdentity getCellIdentity();
     method @Nullable public android.telephony.DataSpecificRegistrationStates getDataSpecificStates();
     method public int getDomain();
     method public int getRegState();
@@ -7638,9 +7710,25 @@
     field public static final int SERVICE_TYPE_VOICE = 1; // 0x1
   }
 
+  public static class NetworkRegistrationState.Builder {
+    ctor public NetworkRegistrationState.Builder();
+    method @NonNull public android.telephony.NetworkRegistrationState build();
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setAccessNetworkTechnology(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setAvailableServices(@NonNull int[]);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setDomain(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setEmergencyOnly(boolean);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setNrStatus(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRegState(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRejectCause(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setRoamingType(int);
+    method @NonNull public android.telephony.NetworkRegistrationState.Builder setTransportType(int);
+  }
+
   public abstract class NetworkService extends android.app.Service {
     ctor public NetworkService();
-    method protected abstract android.telephony.NetworkService.NetworkServiceProvider createNetworkServiceProvider(int);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int);
     field public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
   }
 
@@ -7648,12 +7736,12 @@
     ctor public NetworkService.NetworkServiceProvider(int);
     method public abstract void close();
     method public void getNetworkRegistrationState(int, @NonNull android.telephony.NetworkServiceCallback);
-    method public final int getSlotId();
+    method public final int getSlotIndex();
     method public final void notifyNetworkRegistrationStateChanged();
   }
 
   public class NetworkServiceCallback {
-    method public void onGetNetworkRegistrationStateComplete(int, android.telephony.NetworkRegistrationState);
+    method public void onGetNetworkRegistrationStateComplete(int, @Nullable android.telephony.NetworkRegistrationState);
     field public static final int RESULT_ERROR_BUSY = 3; // 0x3
     field public static final int RESULT_ERROR_FAILED = 5; // 0x5
     field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
@@ -7875,7 +7963,7 @@
     method public void requestEmbeddedSubscriptionInfoListRefresh(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @NonNull java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
     field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
     field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
@@ -7942,7 +8030,7 @@
     method @Deprecated public boolean getDataEnabled(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getLogicalToPhysicalSlotMapping();
     method public static long getMaxNumberVerificationTimeoutMillis();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmap();
@@ -8085,7 +8173,6 @@
 
   public final class DataCallResponse implements android.os.Parcelable {
     ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.lang.String>, int);
-    ctor public DataCallResponse(android.os.Parcel);
     method public int describeContents();
     method public int getActive();
     method @NonNull public java.util.List<android.net.LinkAddress> getAddresses();
@@ -8103,19 +8190,19 @@
   }
 
   public final class DataProfile implements android.os.Parcelable {
-    method public String getApn();
+    method @NonNull public String getApn();
     method public int getAuthType();
     method public int getBearerBitmap();
     method public int getMaxConns();
     method public int getMaxConnsTime();
     method public int getMtu();
-    method public String getPassword();
+    method @Nullable public String getPassword();
     method public int getProfileId();
     method public int getProtocol();
     method public int getRoamingProtocol();
     method public int getSupportedApnTypesBitmap();
     method public int getType();
-    method public String getUserName();
+    method @Nullable public String getUserName();
     method public int getWaitTime();
     method public boolean isEnabled();
     method public boolean isPersistent();
@@ -8127,7 +8214,8 @@
 
   public abstract class DataService extends android.app.Service {
     ctor public DataService();
-    method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int);
     field public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
     field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
     field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
@@ -8139,7 +8227,7 @@
     method public abstract void close();
     method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
     method public void getDataCallList(@NonNull android.telephony.data.DataServiceCallback);
-    method public final int getSlotId();
+    method public final int getSlotIndex();
     method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
     method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @Nullable android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @Nullable android.telephony.data.DataServiceCallback);
@@ -8147,12 +8235,12 @@
   }
 
   public class DataServiceCallback {
-    method public void onDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
+    method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
     method public void onDeactivateDataCallComplete(int);
-    method public void onGetDataCallListComplete(int, java.util.List<android.telephony.data.DataCallResponse>);
+    method public void onGetDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>);
     method public void onSetDataProfileComplete(int);
     method public void onSetInitialAttachApnComplete(int);
-    method public void onSetupDataCallComplete(int, android.telephony.data.DataCallResponse);
+    method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse);
     field public static final int RESULT_ERROR_BUSY = 3; // 0x3
     field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
     field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
@@ -8418,7 +8506,7 @@
   }
 
   public class ImsCallSessionListener {
-    method public void callQualityChanged(android.telephony.CallQuality);
+    method public void callQualityChanged(@NonNull android.telephony.CallQuality);
     method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
     method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
@@ -8443,7 +8531,7 @@
     method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
     method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
-    method public void callSessionRttAudioIndicatorChanged(android.telephony.ims.ImsStreamMediaProfile);
+    method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
     method public void callSessionRttMessageReceived(String);
     method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
     method public void callSessionRttModifyResponseReceived(int);
@@ -8484,7 +8572,7 @@
   public class ImsException extends java.lang.Exception {
     ctor public ImsException(@Nullable String);
     ctor public ImsException(@Nullable String, int);
-    ctor public ImsException(@Nullable String, int, Throwable);
+    ctor public ImsException(@Nullable String, int, @Nullable Throwable);
     method public int getCode();
     field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
     field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
@@ -8492,13 +8580,13 @@
   }
 
   public final class ImsExternalCallState implements android.os.Parcelable {
-    ctor public ImsExternalCallState(String, android.net.Uri, android.net.Uri, boolean, int, int, boolean);
+    ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
     method public int describeContents();
-    method public android.net.Uri getAddress();
+    method @NonNull public android.net.Uri getAddress();
     method public int getCallId();
     method public int getCallState();
     method public int getCallType();
-    method public android.net.Uri getLocalAddress();
+    method @Nullable public android.net.Uri getLocalAddress();
     method public boolean isCallHeld();
     method public boolean isCallPullable();
     method public void writeToParcel(android.os.Parcel, int);
@@ -8508,7 +8596,7 @@
   }
 
   public class ImsMmTelManager {
-    method public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+    method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
@@ -8517,7 +8605,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -8536,15 +8624,15 @@
 
   public static class ImsMmTelManager.CapabilityCallback {
     ctor public ImsMmTelManager.CapabilityCallback();
-    method public void onCapabilitiesStatusChanged(android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+    method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
   }
 
   public static class ImsMmTelManager.RegistrationCallback {
     ctor public ImsMmTelManager.RegistrationCallback();
     method public void onRegistered(int);
     method public void onRegistering(int);
-    method public void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
-    method public void onUnregistered(android.telephony.ims.ImsReasonInfo);
+    method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
+    method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
   }
 
   public final class ImsReasonInfo implements android.os.Parcelable {
@@ -8747,12 +8835,12 @@
   public final class ImsSsData implements android.os.Parcelable {
     ctor public ImsSsData(int, int, int, int, int);
     method public int describeContents();
-    method public android.telephony.ims.ImsCallForwardInfo[] getCallForwardInfo();
+    method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
     method public int getRequestType();
     method public int getResult();
     method public int getServiceClass();
     method public int getServiceType();
-    method @NonNull public android.telephony.ims.ImsSsInfo[] getSuppServiceInfo();
+    method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
     method public int getTeleserviceType();
     method public boolean isTypeBarring();
     method public boolean isTypeCf();
@@ -8812,11 +8900,11 @@
     field public static final int SS_WAIT = 12; // 0xc
   }
 
-  public static class ImsSsData.Builder {
+  public static final class ImsSsData.Builder {
     ctor public ImsSsData.Builder(int, int, int, int, int);
     method @NonNull public android.telephony.ims.ImsSsData build();
-    method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull android.telephony.ims.ImsCallForwardInfo[]);
-    method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull android.telephony.ims.ImsSsInfo[]);
+    method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
+    method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
   }
 
   public final class ImsSsInfo implements android.os.Parcelable {
@@ -8825,7 +8913,7 @@
     method public int getClirInterrogationStatus();
     method public int getClirOutgoingState();
     method @Deprecated public String getIcbNum();
-    method public String getIncomingCommunicationBarringNumber();
+    method @Nullable public String getIncomingCommunicationBarringNumber();
     method public int getProvisionStatus();
     method public int getStatus();
     method public void writeToParcel(android.os.Parcel, int);
@@ -8846,7 +8934,7 @@
     field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
   }
 
-  public static class ImsSsInfo.Builder {
+  public static final class ImsSsInfo.Builder {
     ctor public ImsSsInfo.Builder(int);
     method @NonNull public android.telephony.ims.ImsSsInfo build();
     method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
@@ -8953,14 +9041,14 @@
   }
 
   public class ProvisioningManager {
-    method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
+    method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
     method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int);
     method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
-    method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getProvisioningStringValue(int);
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
     method @WorkerThread @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, String);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
     field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
     field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
@@ -9346,7 +9434,7 @@
     method public static void logFileOperationFailure(int, int);
     method public static void logFilePick(int, long, int, boolean, int, int, int);
     method public static void logInvalidScopedAccessRequest(int);
-    method public static void logPickerLaunchedFrom(String);
+    method public static void logPickerLaunchedFrom(@Nullable String);
     method public static void logRootVisited(int, int);
     method public static void logSearchMode(int);
     method public static void logSearchType(int);
@@ -9626,16 +9714,16 @@
 
   public final class WebViewDelegate {
     method public void addWebViewAssetPath(android.content.Context);
-    method public void callDrawGlFunction(android.graphics.Canvas, long);
-    method public void callDrawGlFunction(@NonNull android.graphics.Canvas, long, @Nullable Runnable);
-    method public boolean canInvokeDrawGlFunctor(android.view.View);
-    method public void detachDrawGlFunctor(android.view.View, long);
+    method @Deprecated public void callDrawGlFunction(android.graphics.Canvas, long);
+    method @Deprecated public void callDrawGlFunction(@NonNull android.graphics.Canvas, long, @Nullable Runnable);
+    method @Deprecated public boolean canInvokeDrawGlFunctor(android.view.View);
+    method @Deprecated public void detachDrawGlFunctor(android.view.View, long);
     method public void drawWebViewFunctor(@NonNull android.graphics.Canvas, int);
     method public android.app.Application getApplication();
     method public String getDataDirectorySuffix();
     method public String getErrorString(android.content.Context, int);
     method public int getPackageId(android.content.res.Resources, String);
-    method public void invokeDrawGlFunctor(android.view.View, long, boolean);
+    method @Deprecated public void invokeDrawGlFunctor(android.view.View, long, boolean);
     method public boolean isMultiProcessEnabled();
     method public boolean isTraceTagEnabled();
     method public void setOnTraceEnabledChangeListener(android.webkit.WebViewDelegate.OnTraceEnabledChangeListener);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 22a3fb3..7e04469 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -60,6 +60,17 @@
 
 }
 
+package android.location {
+
+  public class LocationManager {
+    method @Deprecated public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+    method @Deprecated public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+    method @Deprecated public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
+    method @Deprecated public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+  }
+
+}
+
 package android.media.tv {
 
   public final class TvInputManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index e588847..3b02954 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -41,7 +41,6 @@
 
   public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
     method public void onMovedToDisplay(int, android.content.res.Configuration);
-    method public void setInheritShowWhenLocked(boolean);
   }
 
   public class ActivityManager {
@@ -193,29 +192,36 @@
     field public static final String OPSTR_WRITE_SMS = "android:write_sms";
     field public static final String OPSTR_WRITE_WALLPAPER = "android:write_wallpaper";
     field public static final int OP_COARSE_LOCATION = 0; // 0x0
+    field public static final int OP_FLAGS_ALL = 31; // 0x1f
+    field public static final int OP_FLAG_SELF = 1; // 0x1
+    field public static final int OP_FLAG_TRUSTED_PROXIED = 8; // 0x8
+    field public static final int OP_FLAG_TRUSTED_PROXY = 2; // 0x2
+    field public static final int OP_FLAG_UNTRUSTED_PROXIED = 16; // 0x10
+    field public static final int OP_FLAG_UNTRUSTED_PROXY = 4; // 0x4
     field public static final int OP_RECORD_AUDIO = 27; // 0x1b
+    field public static final int OP_START_FOREGROUND = 76; // 0x4c
     field public static final int OP_SYSTEM_ALERT_WINDOW = 24; // 0x18
-    field public static final int UID_STATE_BACKGROUND = 5; // 0x5
-    field public static final int UID_STATE_CACHED = 6; // 0x6
-    field public static final int UID_STATE_FOREGROUND = 4; // 0x4
-    field public static final int UID_STATE_FOREGROUND_SERVICE = 3; // 0x3
-    field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 2; // 0x2
-    field public static final int UID_STATE_PERSISTENT = 0; // 0x0
-    field public static final int UID_STATE_TOP = 1; // 0x1
+    field public static final int UID_STATE_BACKGROUND = 600; // 0x258
+    field public static final int UID_STATE_CACHED = 700; // 0x2bc
+    field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
+    field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
+    field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
+    field public static final int UID_STATE_PERSISTENT = 100; // 0x64
+    field public static final int UID_STATE_TOP = 200; // 0xc8
   }
 
   public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
     method public int describeContents();
-    method public long getAccessCount(int);
-    method public long getAccessDuration(int);
-    method public long getBackgroundAccessCount();
-    method public long getBackgroundAccessDuration();
-    method public long getBackgroundRejectCount();
-    method public long getForegroundAccessCount();
-    method public long getForegroundAccessDuration();
-    method public long getForegroundRejectCount();
+    method public long getAccessCount(int, int, int);
+    method public long getAccessDuration(int, int, int);
+    method public long getBackgroundAccessCount(int);
+    method public long getBackgroundAccessDuration(int);
+    method public long getBackgroundRejectCount(int);
+    method public long getForegroundAccessCount(int);
+    method public long getForegroundAccessDuration(int);
+    method public long getForegroundRejectCount(int);
     method @NonNull public String getOpName();
-    method public long getRejectCount(int);
+    method public long getRejectCount(int, int, int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOp> CREATOR;
   }
@@ -228,9 +234,9 @@
     method public int getUidCount();
     method @Nullable public android.app.AppOpsManager.HistoricalUidOps getUidOps(int);
     method @NonNull public android.app.AppOpsManager.HistoricalUidOps getUidOpsAt(int);
-    method public void increaseAccessCount(int, int, @NonNull String, int, long);
-    method public void increaseAccessDuration(int, int, @NonNull String, int, long);
-    method public void increaseRejectCount(int, int, @NonNull String, int, long);
+    method public void increaseAccessCount(int, int, @NonNull String, int, int, long);
+    method public void increaseAccessDuration(int, int, @NonNull String, int, int, long);
+    method public void increaseRejectCount(int, int, @NonNull String, int, int, long);
     method public void offsetBeginAndEndTime(long);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
@@ -242,6 +248,7 @@
   public static final class AppOpsManager.HistoricalOpsRequest.Builder {
     ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
+    method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
     method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
@@ -271,6 +278,31 @@
     method public void onOpActiveChanged(int, int, String, boolean);
   }
 
+  public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getDuration();
+    method public long getLastAccessBackgroundTime(int);
+    method public long getLastAccessForegroundTime(int);
+    method public long getLastAccessTime(int);
+    method public long getLastAccessTime(int, int, int);
+    method public long getLastBackgroundDuration(int);
+    method public long getLastDuration(int, int, int);
+    method public long getLastForegroundDuration(int);
+    method public long getLastRejectBackgroundTime(int);
+    method public long getLastRejectForegroundTime(int);
+    method public long getLastRejectTime(int);
+    method public long getLastRejectTime(int, int, int);
+    method public int getMode();
+    method @NonNull public String getOpStr();
+    method @Nullable public String getProxyPackageName();
+    method @Nullable public String getProxyPackageName(int, int);
+    method public int getProxyUid();
+    method public int getProxyUid(int, int);
+    method public boolean isRunning();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEntry> CREATOR;
+  }
+
   public class DownloadManager {
     field public static final String COLUMN_MEDIASTORE_URI = "mediastore_uri";
   }
@@ -490,6 +522,7 @@
     method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
     method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
     method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
+    field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
   }
 
   public interface RoleManagerCallback {
@@ -530,11 +563,13 @@
     ctor public AutofillOptions(int, boolean);
     method public int describeContents();
     method public static android.content.AutofillOptions forWhitelistingItself();
+    method public boolean isAugmentedAutofillEnabled(@NonNull android.content.Context);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
-    field public boolean augmentedEnabled;
+    field public boolean augmentedAutofillEnabled;
     field public final boolean compatModeEnabled;
     field public final int loggingLevel;
+    field @Nullable public android.util.ArraySet<android.content.ComponentName> whitelistedActivitiesForAugmentedAutofill;
   }
 
   public final class ContentCaptureOptions implements android.os.Parcelable {
@@ -634,7 +669,7 @@
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
-    field public String backgroundPermission;
+    field @Nullable public final String backgroundPermission;
   }
 
   public final class ShortcutInfo implements android.os.Parcelable {
@@ -903,16 +938,16 @@
   }
 
   public class LocationManager {
-    method public String[] getBackgroundThrottlingWhitelist();
-    method public String[] getIgnoreSettingsWhitelist();
+    method @NonNull public String[] getBackgroundThrottlingWhitelist();
+    method @NonNull public String[] getIgnoreSettingsWhitelist();
     method @NonNull public java.util.List<android.location.LocationRequest> getTestProviderCurrentRequests(String);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(android.location.LocationRequest, android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, android.os.UserHandle);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
   }
 
   public final class LocationRequest implements android.os.Parcelable {
-    method public static android.location.LocationRequest create();
+    method @NonNull public static android.location.LocationRequest create();
     method public int describeContents();
     method public long getExpireAt();
     method public long getFastestInterval();
@@ -920,14 +955,14 @@
     method public int getNumUpdates();
     method public int getQuality();
     method public boolean isLocationSettingsIgnored();
-    method public android.location.LocationRequest setExpireAt(long);
-    method public android.location.LocationRequest setExpireIn(long);
-    method public android.location.LocationRequest setFastestInterval(long);
-    method public android.location.LocationRequest setInterval(long);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
-    method public android.location.LocationRequest setNumUpdates(int);
-    method public android.location.LocationRequest setProvider(String);
-    method public android.location.LocationRequest setQuality(int);
+    method @NonNull public android.location.LocationRequest setExpireAt(long);
+    method @NonNull public android.location.LocationRequest setExpireIn(long);
+    method @NonNull public android.location.LocationRequest setFastestInterval(long);
+    method @NonNull public android.location.LocationRequest setInterval(long);
+    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+    method @NonNull public android.location.LocationRequest setNumUpdates(int);
+    method @NonNull public android.location.LocationRequest setProvider(@NonNull String);
+    method @NonNull public android.location.LocationRequest setQuality(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACCURACY_BLOCK = 102; // 0x66
     field public static final int ACCURACY_CITY = 104; // 0x68
@@ -978,7 +1013,7 @@
     method public android.media.MediaPlayer2.DrmInfo getDrmInfo(@NonNull android.media.DataSourceDesc);
     method public android.media.MediaDrm.KeyRequest getDrmKeyRequest(@NonNull android.media.DataSourceDesc, @Nullable byte[], @Nullable byte[], @Nullable String, int, @Nullable java.util.Map<java.lang.String,java.lang.String>) throws android.media.MediaPlayer2.NoDrmSchemeException;
     method public String getDrmPropertyString(@NonNull android.media.DataSourceDesc, @NonNull String) throws android.media.MediaPlayer2.NoDrmSchemeException;
-    method public Object prepareDrm(@NonNull android.media.DataSourceDesc, @NonNull java.util.UUID);
+    method @NonNull public Object prepareDrm(@NonNull android.media.DataSourceDesc, @NonNull java.util.UUID);
     method public byte[] provideDrmKeyResponse(@NonNull android.media.DataSourceDesc, @Nullable byte[], @NonNull byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer2.NoDrmSchemeException;
     method public void releaseDrm(@NonNull android.media.DataSourceDesc) throws android.media.MediaPlayer2.NoDrmSchemeException;
     method public void restoreDrmKeys(@NonNull android.media.DataSourceDesc, @NonNull byte[]) throws android.media.MediaPlayer2.NoDrmSchemeException;
@@ -1394,19 +1429,16 @@
 package android.net.util {
 
   public class SocketUtils {
-    method public static void addArpEntry(java.net.Inet4Address, android.net.MacAddress, String, java.io.FileDescriptor) throws java.io.IOException;
-    method public static void attachControlPacketFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
-    method public static void attachDhcpFilter(java.io.FileDescriptor) throws java.net.SocketException;
-    method public static void attachRaFilter(java.io.FileDescriptor, int) throws java.net.SocketException;
-    method public static void bindSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
-    method public static void bindSocketToInterface(java.io.FileDescriptor, String) throws android.system.ErrnoException;
-    method public static void closeSocket(java.io.FileDescriptor) throws java.io.IOException;
-    method public static void connectSocket(java.io.FileDescriptor, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void addArpEntry(@NonNull java.net.Inet4Address, @NonNull android.net.MacAddress, @NonNull String, @NonNull java.io.FileDescriptor) throws java.io.IOException;
+    method public static void attachControlPacketFilter(@NonNull java.io.FileDescriptor, int) throws java.net.SocketException;
+    method public static void attachDhcpFilter(@NonNull java.io.FileDescriptor) throws java.net.SocketException;
+    method public static void attachRaFilter(@NonNull java.io.FileDescriptor, int) throws java.net.SocketException;
+    method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException;
+    method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
     method public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
     method public static java.net.SocketAddress makePacketSocketAddress(short, int);
-    method public static java.net.SocketAddress makePacketSocketAddress(int, byte[]);
-    method public static void sendTo(java.io.FileDescriptor, byte[], int, int, int, java.net.SocketAddress) throws android.system.ErrnoException, java.net.SocketException;
-    method public static void setSocketTimeValueOption(java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
+    method public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+    method public static void setSocketTimeValueOption(@NonNull java.io.FileDescriptor, int, int, long) throws android.system.ErrnoException;
   }
 
 }
@@ -1487,7 +1519,7 @@
     method public final void putInt64Array(long, long[]);
     method public final void putInt8(long, byte);
     method public final void putInt8Array(long, byte[]);
-    method public final void putNativeHandle(long, android.os.NativeHandle);
+    method public final void putNativeHandle(long, @Nullable android.os.NativeHandle);
     method public final void putString(long, String);
     method public static Boolean[] wrapArray(@NonNull boolean[]);
     method public static Long[] wrapArray(@NonNull long[]);
@@ -1507,7 +1539,7 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
-    method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
+    method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
     method public final short readInt16();
@@ -1518,8 +1550,8 @@
     method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
     method public final byte readInt8();
     method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
-    method public final android.os.NativeHandle readNativeHandle();
-    method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
+    method @Nullable public final android.os.NativeHandle readNativeHandle();
+    method @NonNull public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
     method public final String readString();
     method public final java.util.ArrayList<java.lang.String> readStringVector();
     method public final android.os.IHwBinder readStrongBinder();
@@ -1543,8 +1575,8 @@
     method public final void writeInt8(byte);
     method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
     method public final void writeInterfaceToken(String);
-    method public final void writeNativeHandle(android.os.NativeHandle);
-    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
+    method public final void writeNativeHandle(@Nullable android.os.NativeHandle);
+    method public final void writeNativeHandleVector(@NonNull java.util.ArrayList<android.os.NativeHandle>);
     method public final void writeStatus(int);
     method public final void writeString(String);
     method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
@@ -1637,10 +1669,10 @@
     ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
     ctor public NativeHandle(@NonNull java.io.FileDescriptor[], @NonNull int[], boolean);
     method public void close() throws java.io.IOException;
-    method public android.os.NativeHandle dup() throws java.io.IOException;
-    method public java.io.FileDescriptor getFileDescriptor();
-    method public java.io.FileDescriptor[] getFileDescriptors();
-    method public int[] getInts();
+    method @NonNull public android.os.NativeHandle dup() throws java.io.IOException;
+    method @NonNull public java.io.FileDescriptor getFileDescriptor();
+    method @NonNull public java.io.FileDescriptor[] getFileDescriptors();
+    method @NonNull public int[] getInts();
     method public boolean hasSingleFileDescriptor();
   }
 
@@ -1719,9 +1751,9 @@
     method public static int getAppId(int);
     method public int getIdentifier();
     method public static boolean isApp(int);
-    field public static final android.os.UserHandle ALL;
-    field public static final android.os.UserHandle CURRENT;
-    field public static final android.os.UserHandle SYSTEM;
+    field @NonNull public static final android.os.UserHandle ALL;
+    field @NonNull public static final android.os.UserHandle CURRENT;
+    field @NonNull public static final android.os.UserHandle SYSTEM;
   }
 
   public class UserManager {
@@ -1957,6 +1989,7 @@
   }
 
   public static interface DeviceConfig.OnPropertyChangedListener {
+    method public default void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
     method public void onPropertyChanged(String, String, String);
   }
 
@@ -1965,6 +1998,16 @@
     field public static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED = "location_access_check_enabled";
   }
 
+  public static class DeviceConfig.Properties {
+    method public boolean getBoolean(@NonNull String, boolean);
+    method public float getFloat(@NonNull String, float);
+    method public int getInt(@NonNull String, int);
+    method @NonNull public java.util.Set<java.lang.String> getKeyset();
+    method public long getLong(@NonNull String, long);
+    method @NonNull public String getNamespace();
+    method @Nullable public String getString(@NonNull String, @Nullable String);
+  }
+
   public final class MediaStore {
     method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
@@ -1998,6 +2041,7 @@
     field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
     field public static final String DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = "data_stall_consecutive_dns_timeout_threshold";
     field public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
+    field public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1; // 0x1
     field public static final String DATA_STALL_MIN_EVALUATE_INTERVAL = "data_stall_min_evaluate_interval";
     field public static final String DATA_STALL_VALID_DNS_TIME_THRESHOLD = "data_stall_valid_dns_time_threshold";
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
@@ -2066,8 +2110,8 @@
   }
 
   public class DeviceIdAttestationException extends java.lang.Exception {
-    ctor public DeviceIdAttestationException(String);
-    ctor public DeviceIdAttestationException(String, Throwable);
+    ctor public DeviceIdAttestationException(@Nullable String);
+    ctor public DeviceIdAttestationException(@Nullable String, @Nullable Throwable);
   }
 
   public static final class KeyGenParameterSpec.Builder {
@@ -2286,7 +2330,38 @@
   }
 
   public abstract class NotificationListenerService extends android.app.Service {
-    method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, android.service.notification.NotificationStats, int);
+    method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
+  }
+
+  public final class NotificationStats implements android.os.Parcelable {
+    ctor public NotificationStats();
+    method public int describeContents();
+    method public int getDismissalSentiment();
+    method public int getDismissalSurface();
+    method public boolean hasDirectReplied();
+    method public boolean hasExpanded();
+    method public boolean hasInteracted();
+    method public boolean hasSeen();
+    method public boolean hasSnoozed();
+    method public boolean hasViewedSettings();
+    method public void setDirectReplied();
+    method public void setDismissalSentiment(int);
+    method public void setDismissalSurface(int);
+    method public void setExpanded();
+    method public void setSeen();
+    method public void setSnoozed();
+    method public void setViewedSettings();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.NotificationStats> CREATOR;
+    field public static final int DISMISSAL_AOD = 2; // 0x2
+    field public static final int DISMISSAL_NOT_DISMISSED = -1; // 0xffffffff
+    field public static final int DISMISSAL_OTHER = 0; // 0x0
+    field public static final int DISMISSAL_PEEK = 1; // 0x1
+    field public static final int DISMISSAL_SHADE = 3; // 0x3
+    field public static final int DISMISS_SENTIMENT_NEGATIVE = 0; // 0x0
+    field public static final int DISMISS_SENTIMENT_NEUTRAL = 1; // 0x1
+    field public static final int DISMISS_SENTIMENT_POSITIVE = 2; // 0x2
+    field public static final int DISMISS_SENTIMENT_UNKNOWN = -1000; // 0xfffffc18
   }
 
   public final class SnoozeCriterion implements android.os.Parcelable {
@@ -2320,10 +2395,6 @@
     method public android.telecom.Connection getPrimaryConnection();
   }
 
-  public final class PhoneAccountSuggestion implements android.os.Parcelable {
-    ctor public PhoneAccountSuggestion(@NonNull android.telecom.PhoneAccountHandle, int, boolean);
-  }
-
   public class PhoneAccountSuggestionService extends android.app.Service {
     ctor public PhoneAccountSuggestionService();
     method public void onAccountSuggestionRequest(@NonNull String);
@@ -2335,7 +2406,7 @@
   public class TelecomManager {
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCurrentTtyMode();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(android.telecom.PhoneAccountHandle);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
     field public static final int TTY_MODE_FULL = 1; // 0x1
     field public static final int TTY_MODE_HCO = 2; // 0x2
     field public static final int TTY_MODE_OFF = 0; // 0x0
@@ -2732,6 +2803,10 @@
     field public static final int CALLBACK_ANIMATION = 1; // 0x1
   }
 
+  public final class Display {
+    method public boolean hasAccess(int);
+  }
+
   public class FocusFinder {
     method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
   }
@@ -2808,7 +2883,7 @@
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
     field public CharSequence accessibilityTitle;
-    field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x200, equals=0x200, name="INHERIT_TRANSLUCENT_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION")}) public int privateFlags;
+    field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x200, equals=0x200, name="INHERIT_TRANSLUCENT_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x400, equals=0x400, name="KEYGUARD"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC")}) public int privateFlags;
   }
 
 }
@@ -2996,7 +3071,7 @@
     method public abstract String value();
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface InspectableProperty {
+  @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 {};
@@ -3023,6 +3098,7 @@
     enum_constant public static final android.view.inspector.InspectableProperty.ValueType INT_ENUM;
     enum_constant public static final android.view.inspector.InspectableProperty.ValueType INT_FLAG;
     enum_constant public static final android.view.inspector.InspectableProperty.ValueType NONE;
+    enum_constant public static final android.view.inspector.InspectableProperty.ValueType RESOURCE_ID;
   }
 
 }
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index a1341fb..f4c3e9c 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -287,11 +287,20 @@
 bool CheckOverlayable(const LoadedPackage& target_package,
                       const utils::OverlayManifestInfo& overlay_info,
                       const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
+  static constexpr const PolicyBitmask sDefaultPolicies =
+      PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION |
+      PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
+
+  // If the resource does not have an overlayable definition, allow the resource to be overlaid if
+  // the overlay is preinstalled or signed with the same signature as the target.
+  if (!target_package.DefinesOverlayable()) {
+    return (sDefaultPolicies & fulfilled_policies) != 0;
+  }
+
   const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
   if (overlayable_info == nullptr) {
-    // If the resource does not have an overlayable definition, allow the resource to be overlaid.
-    // Once overlayable enforcement is turned on, this check will return false.
-    return !target_package.DefinesOverlayable();
+    // Do not allow non-overlayable resources to be overlaid.
+    return false;
   }
 
   if (overlay_info.target_name != overlayable_info->name) {
@@ -427,6 +436,12 @@
     matching_resources.Add(target_resid, overlay_resid);
   }
 
+  if (matching_resources.Map().empty()) {
+    out_error << "overlay \"" << overlay_apk_path << "\" does not successfully overlay any resource"
+              << std::endl;
+    return nullptr;
+  }
+
   // encode idmap data
   std::unique_ptr<IdmapData> data(new IdmapData());
   const auto types_end = matching_resources.Map().cend();
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index bbfbad9..8d65428 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -173,20 +173,27 @@
   ASSERT_THAT(idmap, IsNull());
 }
 
-TEST(IdmapTests, CreateIdmapFromApkAssets) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+void CreateIdmap(const StringPiece& target_apk_path, const StringPiece& overlay_apk_path,
+                 const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
+                 std::unique_ptr<const Idmap>* out_idmap) {
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path.to_string());
   ASSERT_THAT(target_apk, NotNull());
 
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path.to_string());
   ASSERT_THAT(overlay_apk, NotNull());
 
   std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
+  *out_idmap =
+      Idmap::FromApkAssets(target_apk_path.to_string(), *target_apk, overlay_apk_path.to_string(),
+                           *overlay_apk, fulfilled_policies, enforce_overlayable, error);
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssets) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
@@ -226,19 +233,12 @@
 
 // Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/system-overlay/system-overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -263,21 +263,12 @@
 }
 
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/signature-overlay/signature-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           policy_flags, /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/signature-overlay/signature-overlay.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -298,52 +289,15 @@
   ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/policy_signature
 }
 
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/signature-overlay/signature-overlay.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           policy_flags, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 0U);  // can't overlay, so contains nothing
-}
-
 // Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -369,20 +323,13 @@
 
 // Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
-                           /* enforce_overlayable */ false, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path,
+              PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ false, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -409,63 +356,13 @@
   ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
 }
 
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
-TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() +
-                                     "/system-overlay-invalid/system-overlay-invalid.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
-  ASSERT_THAT(idmap, NotNull());
-
-  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
-  ASSERT_EQ(dataBlocks.size(), 1U);
-
-  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
-
-  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
-  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
-
-  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
-  ASSERT_EQ(types.size(), 1U);
-
-  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
-  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 7U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
-  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
-  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/string/policy_signature
-  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
-}
-
-// The resources of APKs that do not include an overlayable declaration should not restrict what
-// resources can be overlaid.
+// Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable.
 TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
-  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
-  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
-  ASSERT_THAT(target_apk, NotNull());
-
-  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
-  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
-  ASSERT_THAT(overlay_apk, NotNull());
-
-  std::stringstream error;
-  std::unique_ptr<const Idmap> idmap =
-      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
-                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ false, &idmap);
   ASSERT_THAT(idmap, NotNull());
 
   const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
@@ -483,16 +380,81 @@
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
   ASSERT_EQ(types[0]->GetEntryCount(), 1U);
   ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/int1
 
   ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
   ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
   ASSERT_EQ(types[1]->GetEntryCount(), 4U);
   ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
-  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
-  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
-  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
-  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);   // string/str1
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);  // string/str2
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);   // string/str3
+  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);   // string/str4
+}
+
+// Overlays that are not pre-installed and are not signed with the same signature as the target
+// cannot overlay packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPoliciesPublicFail) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-no-name.apk";
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PUBLIC,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, IsNull());
+}
+
+// Overlays that are pre-installed or are signed with the same signature as the target can overlay
+// packages that have not defined overlayable resources.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) {
+  std::unique_ptr<const Idmap> idmap;
+  std::string target_apk_path = GetTestDataPath() + "/target/target-no-overlayable.apk";
+  std::string overlay_apk_path =
+      GetTestDataPath() + "/system-overlay-invalid/system-overlay-invalid.apk";
+
+  auto CheckEntries = [&]() -> void {
+    const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+    ASSERT_EQ(dataBlocks.size(), 1U);
+
+    const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+    ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+    ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+    const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+    ASSERT_EQ(types.size(), 1U);
+
+    ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+    ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+    ASSERT_EQ(types[0]->GetEntryCount(), 7U);
+    ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+    ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
+    ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
+    ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
+    ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
+    ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/string/policy_signature
+    ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system
+    ASSERT_EQ(types[0]->GetEntry(6), 0x0006U);  // string/policy_system_vendor
+  };
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_PRODUCT_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SYSTEM_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
+
+  CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_VENDOR_PARTITION,
+              /* enforce_overlayable */ true, &idmap);
+  ASSERT_THAT(idmap, NotNull());
+  CheckEntries();
 }
 
 TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
index e879f44..68b9f50 100755
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FRAMEWORK_RES_APK="${ANDROID_BUILD_TOP}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
 
 aapt2 compile --dir res -o compiled.flata
 
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index 7d23c09..6425190 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/cmds/incident_helper/src/ih_util.cpp b/cmds/incident_helper/src/ih_util.cpp
index 012310c..77a56e5 100644
--- a/cmds/incident_helper/src/ih_util.cpp
+++ b/cmds/incident_helper/src/ih_util.cpp
@@ -142,7 +142,7 @@
     }
     if (lineSize - lastIndex > 0) {
         int beginning = lastIndex;
-        if (record.size() == indices.size()) {
+        if (record.size() == indices.size() && !record.empty()) {
             // We've already encountered all of the columns...put whatever is
             // left in the last column.
             record.pop_back();
diff --git a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
index 21ced9c..5d525e6 100644
--- a/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
+++ b/cmds/incident_helper/src/parsers/CpuInfoParser.cpp
@@ -65,8 +65,9 @@
         if (line.empty()) continue;
 
         nline++;
-
-        if (stripPrefix(&line, "Tasks:")) {
+        // The format changes from time to time in toybox/toys/posix/ps.c
+        // With -H, it prints Threads instead of Tasks (FLAG(H)?"Thread":"Task")
+        if (stripPrefix(&line, "Threads:")) {
             writeSuffixLine(&proto, CpuInfoProto::TASK_STATS, line, COMMA_DELIMITER,
                 CpuInfoProto::TaskStats::_FIELD_COUNT,
                 CpuInfoProto::TaskStats::_FIELD_NAMES,
diff --git a/cmds/incident_helper/testdata/cpuinfo.txt b/cmds/incident_helper/testdata/cpuinfo.txt
index ec4a839..aa3afc3 100644
--- a/cmds/incident_helper/testdata/cpuinfo.txt
+++ b/cmds/incident_helper/testdata/cpuinfo.txt
@@ -1,8 +1,8 @@
-Tasks: 2038 total,   1 running,2033 sleeping,   0 stopped,   0 zombie
+Threads: 2038 total,   1 running,2033 sleeping,   0 stopped,   0 zombie
 
-Mem:   3842668k total,  3761936k used,    80732k free,   220188k buffers
+  Mem:   3842668k total,  3761936k used,    80732k free,   220188k buffers
 
-Swap:   524284k total,    25892k used,   498392k free,  1316952k cached
+ Swap:   524284k total,    25892k used,   498392k free,  1316952k cached
 
 400%cpu  17%user   0%nice  43%sys 338%idle   0%iow   0%irq   1%sirq   0%host
 
@@ -12,4 +12,4 @@
 29438 29438 rootabcdefghij 20 0 57.9 R  14M 3.8M     top test        top
   916   916 system       18  -2  1.4 S 4.6G 404M  fg system_server   system_server
    28    28 root         -2   0  1.4 S    0    0  bg rcuc/3          [rcuc/3]
-   27    27 root         RT   0  1.4 S    0    0  ta migration/3     [migration/3]
\ No newline at end of file
+   27    27 root         RT   0  1.4 S    0    0  ta migration/3     [migration/3]
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index da72002..7298da6 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -219,6 +219,7 @@
         "tests/anomaly/AnomalyTracker_test.cpp",
         "tests/ConfigManager_test.cpp",
         "tests/external/puller_util_test.cpp",
+        "tests/external/IncidentReportArgs_test.cpp",
         "tests/external/StatsPuller_test.cpp",
         "tests/indexed_priority_queue_test.cpp",
         "tests/LogEntryMatcher_test.cpp",
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index deebd4e..1315750 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,7 +1,6 @@
 bookatz@google.com
 cjyu@google.com
 dwchen@google.com
-gaillard@google.com
 jinyithu@google.com
 joeo@google.com
 kwekua@google.com
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 9ac888b..1526d66 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1210,20 +1210,22 @@
                     (long long)expId);
     }
 
-    vector<uint8_t> buffer;
-    buffer.resize(proto.size());
+    vector<uint8_t> experimentIdsProtoBuffer;
+    experimentIdsProtoBuffer.resize(proto.size());
     size_t pos = 0;
     auto iter = proto.data();
     while (iter.readBuffer() != NULL) {
         size_t toRead = iter.currentToRead();
-        std::memcpy(&(buffer[pos]), iter.readBuffer(), toRead);
+        std::memcpy(&(experimentIdsProtoBuffer[pos]), iter.readBuffer(), toRead);
         pos += toRead;
         iter.rp()->move(toRead);
     }
-    LogEvent event(std::string(String8(trainName).string()), trainVersionCode, requiresStaging,
-                   rollbackEnabled, requiresLowLatencyMonitor, state, buffer, userId);
+
+    std::string trainNameUtf8 = std::string(String8(trainName).string());
+    LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled,
+                   requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId);
     mProcessor->OnLogEvent(&event);
-    StorageManager::writeTrainInfo(trainVersionCode, buffer);
+    StorageManager::writeTrainInfo(trainVersionCode, trainNameUtf8, state, experimentIdsProtoBuffer);
     return Status::ok();
 }
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a983b27..4e540b1 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1568,7 +1568,7 @@
         ROLLBACK_INITIATE = 1;
         ROLLBACK_SUCCESS = 2;
         ROLLBACK_FAILURE = 3;
-        ROLLBACK_ROOT_TRIGGERED = 4;
+        ROLLBACK_BOOT_TRIGGERED = 4;
     }
     optional RollbackType rollback_type = 1;
 
@@ -3005,6 +3005,9 @@
 
     // The elapsed real time of start of the process.
     optional int64 process_start_time_nanos = 9;
+
+    // Min oom adj score considered by lmkd.
+    optional int32 min_oom_score = 10;
 }
 
 /*
@@ -3240,8 +3243,18 @@
         INSTALL_FAILURE = 6;
         INSTALL_CANCELLED = 7;
         INSTALLER_ROLLBACK_REQUESTED = 8;
-        INSTALLER_ROLLBACK_SUCCESS = 9;
-        INSTALLER_ROLLBACK_FAILURE = 10;
+        INSTALLER_ROLLBACK_INITIATED = 9;
+        INSTALLER_ROLLBACK_INITIATED_FAILURE = 10;
+        INSTALLER_ROLLBACK_STAGED = 11;
+        INSTALLER_ROLLBACK_STAGED_FAILURE = 12;
+        INSTALLER_ROLLBACK_BOOT_TRIGGERED = 13;
+        INSTALLER_ROLLBACK_BOOT_TRIGGERED_FAILURE = 14;
+        INSTALLER_ROLLBACK_SUCCESS = 15;
+        INSTALLER_ROLLBACK_FAILURE = 16;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_REMOVE_FROM_QUEUE = 17;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_INITIATED = 18;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_SUCCESS = 19;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_FAILURE = 20;
     }
     optional State state = 6;
     // Possible experiment ids for monitoring this push.
@@ -5650,6 +5663,33 @@
     optional int64 train_version_code = 1;
 
     optional TrainExperimentIds train_experiment_id = 2;
+
+    optional string train_name = 3;
+
+    enum Status {
+        UNKNOWN = 0;
+        INSTALL_REQUESTED = 1;
+        INSTALL_STARTED = 2;
+        INSTALL_STAGED_NOT_READY = 3;
+        INSTALL_STAGED_READY = 4;
+        INSTALL_SUCCESS = 5;
+        INSTALL_FAILURE = 6;
+        INSTALL_CANCELLED = 7;
+        INSTALLER_ROLLBACK_REQUESTED = 8;
+        INSTALLER_ROLLBACK_INITIATED = 9;
+        INSTALLER_ROLLBACK_INITIATED_FAILURE = 10;
+        INSTALLER_ROLLBACK_STAGED = 11;
+        INSTALLER_ROLLBACK_STAGED_FAILURE = 12;
+        INSTALLER_ROLLBACK_BOOT_TRIGGERED = 13;
+        INSTALLER_ROLLBACK_BOOT_TRIGGERED_FAILURE = 14;
+        INSTALLER_ROLLBACK_SUCCESS = 15;
+        INSTALLER_ROLLBACK_FAILURE = 16;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_REMOVE_FROM_QUEUE = 17;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_INITIATED = 18;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_SUCCESS = 19;
+        INSTALLER_ROLLBACK_CANCEL_STAGED_DELETE_SESSION_FAILURE = 20;
+    }
+    optional Status status = 4;
 }
 
 /**
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 0430e4e..d9f5415 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -238,9 +238,12 @@
     mLogdTimestampNs = wallClockTimestampNs;
     mElapsedTimestampNs = elapsedTimestampNs;
     mTagId = android::util::TRAIN_INFO;
+
     mValues.push_back(
             FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainInfo.experimentIds)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
 }
 
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 2fde8b4..753a9a5 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -58,6 +58,8 @@
 
 struct InstallTrainInfo {
     int64_t trainVersionCode;
+    std::string trainName;
+    int32_t status;
     std::vector<uint8_t> experimentIds;
 };
 /**
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 5c6d548..0e91f52 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -324,6 +324,12 @@
     EXPLICIT = 1;
   }
   optional Destination dest = 2;
+
+  // Package name of the incident report receiver.
+  optional string receiver_pkg = 3;
+
+  // Class name of the incident report receiver.
+  optional string receiver_cls = 4;
 }
 
 message PerfettoDetails {
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 165e57c..5df8fb5 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -95,8 +95,8 @@
     close(fd);
 }
 
-bool StorageManager::writeTrainInfo(int64_t trainVersionCode,
-                                    const std::vector<uint8_t>& experimentIds) {
+bool StorageManager::writeTrainInfo(int64_t trainVersionCode, const std::string& trainName,
+                                    int32_t status, const std::vector<uint8_t>& experimentIds) {
     std::lock_guard<std::mutex> lock(sTrainInfoMutex);
 
     deleteAllFiles(TRAIN_INFO_DIR);
@@ -109,7 +109,34 @@
         return false;
     }
 
-    size_t result = write(fd, experimentIds.data(), experimentIds.size());
+    size_t result;
+
+    // Write # of bytes in trainName to file
+    const size_t trainNameSize = trainName.size();
+    const size_t trainNameSizeByteCount = sizeof(trainNameSize);
+    result = write(fd, (uint8_t*)&trainNameSize, trainNameSizeByteCount);
+    if (result != trainNameSizeByteCount) {
+        VLOG("Failed to write %s", file_name.c_str());
+        return false;
+    }
+
+    // Write trainName to file
+    result = write(fd, trainName.c_str(), trainNameSize);
+    if (result != trainNameSize) {
+        VLOG("Failed to write %s", file_name.c_str());
+        return false;
+    }
+
+    // Write status to file
+    const size_t statusByteCount = sizeof(status);
+    result = write(fd, (uint8_t*)&status, statusByteCount);
+    if (result != statusByteCount) {
+        VLOG("Failed to write %s", file_name.c_str());
+        return false;
+    }
+
+    // Write experimentIds to file
+    result = write(fd, experimentIds.data(), experimentIds.size());
     if (result == experimentIds.size()) {
         VLOG("Successfully wrote %s", file_name.c_str());
     } else {
@@ -150,7 +177,27 @@
             string str;
             if (android::base::ReadFdToString(fd, &str)) {
                 close(fd);
-                std::copy(str.begin(), str.end(), std::back_inserter(trainInfo.experimentIds));
+
+                auto it = str.begin();
+
+                // Read # of bytes taken by trainName in the file
+                size_t trainNameSize;
+                const size_t trainNameSizeByteCount = sizeof(trainNameSize);
+                std::copy_n(it, trainNameSizeByteCount, &trainNameSize);
+                it += trainNameSizeByteCount;
+
+                // Read trainName
+                std::copy_n(it, trainNameSize, std::back_inserter(trainInfo.trainName));
+                it += trainNameSize;
+
+                // Read status
+                const size_t statusByteCount = sizeof(trainInfo.status);
+                std::copy_n(it, statusByteCount, &trainInfo.status);
+                it += statusByteCount;
+
+                // Read experimentIds
+                std::copy(it, str.end(), std::back_inserter(trainInfo.experimentIds));
+
                 VLOG("Read train info file successful: %s", fullPath.c_str());
                 return true;
             }
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index d6df867..88280cf 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -44,7 +44,8 @@
     /**
      * Writes train info.
      */
-    static bool writeTrainInfo(int64_t trainVersionCode, const std::vector<uint8_t>& experimentIds);
+    static bool writeTrainInfo(int64_t trainVersionCode, const std::string& trainName,
+                               int32_t status, const std::vector<uint8_t>& experimentIds);
 
     /**
      * Reads train info.
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 0ed2d75..7c2d242 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -162,6 +162,10 @@
     }
     incidentReport.setDest(dest);
 
+    incidentReport.setReceiverPkg(config.receiver_pkg());
+
+    incidentReport.setReceiverCls(config.receiver_cls());
+
     sp<IIncidentManager> service = interface_cast<IIncidentManager>(
             defaultServiceManager()->getService(android::String16("incident")));
     if (service == nullptr) {
diff --git a/cmds/statsd/tests/external/IncidentReportArgs_test.cpp b/cmds/statsd/tests/external/IncidentReportArgs_test.cpp
new file mode 100644
index 0000000..c170b12
--- /dev/null
+++ b/cmds/statsd/tests/external/IncidentReportArgs_test.cpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <android/os/IncidentReportArgs.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+TEST(IncidentReportArgsTest, testSerialization) {
+    IncidentReportArgs args;
+    args.setAll(0);
+    args.addSection(1000);
+    args.addSection(1001);
+
+    vector<uint8_t> header1;
+    header1.push_back(0x1);
+    header1.push_back(0x2);
+    vector<uint8_t> header2;
+    header1.push_back(0x22);
+    header1.push_back(0x33);
+
+    args.addHeader(header1);
+    args.addHeader(header2);
+
+    args.setDest(1);
+
+    args.setReceiverPkg("com.android.os");
+    args.setReceiverCls("com.android.os.Receiver");
+
+    Parcel out;
+    status_t err = args.writeToParcel(&out);
+    EXPECT_EQ(NO_ERROR, err);
+
+    out.setDataPosition(0);
+
+    IncidentReportArgs args2;
+    err = args2.readFromParcel(&out);
+    EXPECT_EQ(NO_ERROR, err);
+
+    EXPECT_EQ(0, args2.all());
+    set<int> sections;
+    sections.insert(1000);
+    sections.insert(1001);
+    EXPECT_EQ(sections, args2.sections());
+    EXPECT_EQ(1, args2.dest());
+
+    EXPECT_EQ(String16("com.android.os"), args2.receiverPkg());
+    EXPECT_EQ(String16("com.android.os.Receiver"), args2.receiverCls());
+
+    vector<vector<uint8_t>> headers;
+    headers.push_back(header1);
+    headers.push_back(header2);
+    EXPECT_EQ(headers, args2.headers());
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/tests/storage/StorageManager_test.cpp b/cmds/statsd/tests/storage/StorageManager_test.cpp
index f66de05..4564a5d 100644
--- a/cmds/statsd/tests/storage/StorageManager_test.cpp
+++ b/cmds/statsd/tests/storage/StorageManager_test.cpp
@@ -32,16 +32,82 @@
 TEST(StorageManagerTest, TrainInfoReadWriteTest) {
     InstallTrainInfo trainInfo;
     trainInfo.trainVersionCode = 12345;
+    trainInfo.trainName = "This is a train name #)$(&&$";
+    trainInfo.status = 1;
     const char* expIds = "test_ids";
     trainInfo.experimentIds.assign(expIds, expIds + strlen(expIds));
 
-    StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.experimentIds);
+    bool result;
 
-    InstallTrainInfo result;
-    StorageManager::readTrainInfo(result);
-    EXPECT_EQ(trainInfo.trainVersionCode, result.trainVersionCode);
-    EXPECT_EQ(trainInfo.experimentIds.size(), result.experimentIds.size());
-    EXPECT_EQ(trainInfo.experimentIds, result.experimentIds);
+    result = StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.trainName,
+                                            trainInfo.status, trainInfo.experimentIds);
+
+    EXPECT_TRUE(result);
+
+    InstallTrainInfo trainInfoResult;
+    result = StorageManager::readTrainInfo(trainInfoResult);
+    EXPECT_TRUE(result);
+
+    EXPECT_EQ(trainInfo.trainVersionCode, trainInfoResult.trainVersionCode);
+    EXPECT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
+    EXPECT_EQ(trainInfo.trainName, trainInfoResult.trainName);
+    EXPECT_EQ(trainInfo.status, trainInfoResult.status);
+    EXPECT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
+    EXPECT_EQ(trainInfo.experimentIds, trainInfoResult.experimentIds);
+}
+
+TEST(StorageManagerTest, TrainInfoReadWriteEmptyTrainNameTest) {
+    InstallTrainInfo trainInfo;
+    trainInfo.trainVersionCode = 12345;
+    trainInfo.trainName = "";
+    trainInfo.status = 1;
+    const char* expIds = "test_ids";
+    trainInfo.experimentIds.assign(expIds, expIds + strlen(expIds));
+
+    bool result;
+
+    result = StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.trainName,
+                                            trainInfo.status, trainInfo.experimentIds);
+
+    EXPECT_TRUE(result);
+
+    InstallTrainInfo trainInfoResult;
+    result = StorageManager::readTrainInfo(trainInfoResult);
+    EXPECT_TRUE(result);
+
+    EXPECT_EQ(trainInfo.trainVersionCode, trainInfoResult.trainVersionCode);
+    EXPECT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
+    EXPECT_EQ(trainInfo.trainName, trainInfoResult.trainName);
+    EXPECT_EQ(trainInfo.status, trainInfoResult.status);
+    EXPECT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
+    EXPECT_EQ(trainInfo.experimentIds, trainInfoResult.experimentIds);
+}
+
+TEST(StorageManagerTest, TrainInfoReadWriteTrainNameSizeOneTest) {
+    InstallTrainInfo trainInfo;
+    trainInfo.trainVersionCode = 12345;
+    trainInfo.trainName = "{";
+    trainInfo.status = 1;
+    const char* expIds = "test_ids";
+    trainInfo.experimentIds.assign(expIds, expIds + strlen(expIds));
+
+    bool result;
+
+    result = StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.trainName,
+                                            trainInfo.status, trainInfo.experimentIds);
+
+    EXPECT_TRUE(result);
+
+    InstallTrainInfo trainInfoResult;
+    result = StorageManager::readTrainInfo(trainInfoResult);
+    EXPECT_TRUE(result);
+
+    EXPECT_EQ(trainInfo.trainVersionCode, trainInfoResult.trainVersionCode);
+    EXPECT_EQ(trainInfo.trainName.size(), trainInfoResult.trainName.size());
+    EXPECT_EQ(trainInfo.trainName, trainInfoResult.trainName);
+    EXPECT_EQ(trainInfo.status, trainInfoResult.status);
+    EXPECT_EQ(trainInfo.experimentIds.size(), trainInfoResult.experimentIds.size());
+    EXPECT_EQ(trainInfo.experimentIds, trainInfoResult.experimentIds);
 }
 
 }  // namespace statsd
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index e6ba40d..ff8dec1 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -5,21 +5,10 @@
 Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/accounts/IAccountAuthenticator$Stub;-><init>()V
 Landroid/accounts/IAccountAuthenticator$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountAuthenticator;
-Landroid/accounts/IAccountAuthenticator;->addAccount(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->confirmCredentials(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->editProperties(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->getAccountRemovalAllowed(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;)V
-Landroid/accounts/IAccountAuthenticator;->getAuthToken(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;)V
-Landroid/accounts/IAccountAuthenticator;->getAuthTokenLabel(Landroid/accounts/IAccountAuthenticatorResponse;Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->hasFeatures(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;[Ljava/lang/String;)V
-Landroid/accounts/IAccountAuthenticator;->updateCredentials(Landroid/accounts/IAccountAuthenticatorResponse;Landroid/accounts/Account;Ljava/lang/String;Landroid/os/Bundle;)V
 Landroid/accounts/IAccountAuthenticatorResponse$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/accounts/IAccountAuthenticatorResponse$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/accounts/IAccountAuthenticatorResponse$Stub;-><init>()V
 Landroid/accounts/IAccountAuthenticatorResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountAuthenticatorResponse;
-Landroid/accounts/IAccountAuthenticatorResponse;->onError(ILjava/lang/String;)V
-Landroid/accounts/IAccountAuthenticatorResponse;->onRequestContinued()V
-Landroid/accounts/IAccountAuthenticatorResponse;->onResult(Landroid/os/Bundle;)V
 Landroid/accounts/IAccountManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/accounts/IAccountManager$Stub;-><init>()V
 Landroid/accounts/IAccountManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManager;
@@ -27,8 +16,6 @@
 Landroid/accounts/IAccountManagerResponse$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/accounts/IAccountManagerResponse$Stub;-><init>()V
 Landroid/accounts/IAccountManagerResponse$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accounts/IAccountManagerResponse;
-Landroid/accounts/IAccountManagerResponse;->onError(ILjava/lang/String;)V
-Landroid/accounts/IAccountManagerResponse;->onResult(Landroid/os/Bundle;)V
 Landroid/app/ActivityManagerNative;-><init>()V
 Landroid/app/ActivityThread$AppBindData;-><init>()V
 Landroid/app/ActivityThread$CreateServiceData;-><init>()V
@@ -36,21 +23,9 @@
 Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
-Landroid/app/admin/IDevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
 Landroid/app/backup/IBackupManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/backup/IBackupManager;
-Landroid/app/backup/IBackupManager;->acknowledgeFullBackupOrRestore(IZLjava/lang/String;Ljava/lang/String;Landroid/app/backup/IFullBackupRestoreObserver;)V
-Landroid/app/backup/IBackupManager;->clearBackupData(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/app/backup/IBackupManager;->dataChanged(Ljava/lang/String;)V
-Landroid/app/backup/IBackupManager;->getCurrentTransport()Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->isBackupEnabled()Z
-Landroid/app/backup/IBackupManager;->isBackupServiceActive(I)Z
-Landroid/app/backup/IBackupManager;->listAllTransports()[Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->selectBackupTransport(Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->setAutoRestore(Z)V
-Landroid/app/backup/IBackupManager;->setBackupEnabled(Z)V
 Landroid/app/backup/IFullBackupRestoreObserver$Stub;-><init>()V
 Landroid/app/backup/IRestoreObserver$Stub;-><init>()V
-Landroid/app/DownloadManager;->restartDownload([J)V
 Landroid/app/IActivityController$Stub;-><init>()V
 Landroid/app/IActivityManager$Stub$Proxy;->getConfiguration()Landroid/content/res/Configuration;
 Landroid/app/IActivityManager$Stub$Proxy;->getLaunchedFromUid(Landroid/os/IBinder;)I
@@ -60,187 +35,52 @@
 Landroid/app/IActivityManager$Stub$Proxy;->setActivityController(Landroid/app/IActivityController;Z)V
 Landroid/app/IActivityManager$Stub$Proxy;->updatePersistentConfiguration(Landroid/content/res/Configuration;)V
 Landroid/app/IActivityManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IActivityManager;
-Landroid/app/IActivityManager;->bindService(Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/content/Intent;Ljava/lang/String;Landroid/app/IServiceConnection;ILjava/lang/String;I)I
-Landroid/app/IActivityManager;->broadcastIntent(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;Landroid/content/IIntentReceiver;ILjava/lang/String;Landroid/os/Bundle;[Ljava/lang/String;ILandroid/os/Bundle;ZZI)I
-Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V
-Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V
-Landroid/app/IActivityManager;->checkPermission(Ljava/lang/String;II)I
-Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V
-Landroid/app/IActivityManager;->finishActivity(Landroid/os/IBinder;ILandroid/content/Intent;I)Z
-Landroid/app/IActivityManager;->finishHeavyWeightApp()V
 Landroid/app/IActivityManager;->finishReceiver(Landroid/os/IBinder;ILjava/lang/String;Landroid/os/Bundle;ZI)V
-Landroid/app/IActivityManager;->forceStopPackage(Ljava/lang/String;I)V
-Landroid/app/IActivityManager;->getAllStackInfos()Ljava/util/List;
-Landroid/app/IActivityManager;->getConfiguration()Landroid/content/res/Configuration;
-Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo;
-Landroid/app/IActivityManager;->getFilteredTasks(III)Ljava/util/List;
-Landroid/app/IActivityManager;->getIntentForIntentSender(Landroid/content/IIntentSender;)Landroid/content/Intent;
-Landroid/app/IActivityManager;->getIntentSender(ILjava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I[Landroid/content/Intent;[Ljava/lang/String;ILandroid/os/Bundle;I)Landroid/content/IIntentSender;
-Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String;
-Landroid/app/IActivityManager;->getLaunchedFromUid(Landroid/os/IBinder;)I
-Landroid/app/IActivityManager;->getLockTaskModeState()I
-Landroid/app/IActivityManager;->getMemoryInfo(Landroid/app/ActivityManager$MemoryInfo;)V
-Landroid/app/IActivityManager;->getPackageProcessState(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/app/IActivityManager;->getProcessLimit()I
-Landroid/app/IActivityManager;->getProcessMemoryInfo([I)[Landroid/os/Debug$MemoryInfo;
-Landroid/app/IActivityManager;->getProcessPss([I)[J
-Landroid/app/IActivityManager;->getProviderMimeType(Landroid/net/Uri;I)Ljava/lang/String;
-Landroid/app/IActivityManager;->getRecentTasks(III)Landroid/content/pm/ParceledListSlice;
-Landroid/app/IActivityManager;->getRunningAppProcesses()Ljava/util/List;
-Landroid/app/IActivityManager;->getServices(II)Ljava/util/List;
-Landroid/app/IActivityManager;->getTaskBounds(I)Landroid/graphics/Rect;
-Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I
-Landroid/app/IActivityManager;->getTaskSnapshot(IZ)Landroid/app/ActivityManager$TaskSnapshot;
-Landroid/app/IActivityManager;->handleApplicationStrictModeViolation(Landroid/os/IBinder;ILandroid/os/StrictMode$ViolationInfo;)V
-Landroid/app/IActivityManager;->hang(Landroid/os/IBinder;Z)V
-Landroid/app/IActivityManager;->isInLockTaskMode()Z
-Landroid/app/IActivityManager;->isIntentSenderAnActivity(Landroid/content/IIntentSender;)Z
-Landroid/app/IActivityManager;->isTopOfTask(Landroid/os/IBinder;)Z
-Landroid/app/IActivityManager;->isUserRunning(II)Z
-Landroid/app/IActivityManager;->killAllBackgroundProcesses()V
-Landroid/app/IActivityManager;->killBackgroundProcesses(Ljava/lang/String;I)V
-Landroid/app/IActivityManager;->moveActivityTaskToBack(Landroid/os/IBinder;Z)Z
-Landroid/app/IActivityManager;->moveTaskToFront(IILandroid/os/Bundle;)V
-Landroid/app/IActivityManager;->moveTaskToStack(IIZ)V
-Landroid/app/IActivityManager;->moveTopActivityToPinnedStack(ILandroid/graphics/Rect;)Z
-Landroid/app/IActivityManager;->positionTaskInStack(III)V
-Landroid/app/IActivityManager;->profileControl(Ljava/lang/String;IZLandroid/app/ProfilerInfo;I)Z
-Landroid/app/IActivityManager;->publishContentProviders(Landroid/app/IApplicationThread;Ljava/util/List;)V
-Landroid/app/IActivityManager;->registerProcessObserver(Landroid/app/IProcessObserver;)V
-Landroid/app/IActivityManager;->registerReceiver(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/IIntentReceiver;Landroid/content/IntentFilter;Ljava/lang/String;II)Landroid/content/Intent;
-Landroid/app/IActivityManager;->registerTaskStackListener(Landroid/app/ITaskStackListener;)V
-Landroid/app/IActivityManager;->registerUserSwitchObserver(Landroid/app/IUserSwitchObserver;Ljava/lang/String;)V
-Landroid/app/IActivityManager;->removeContentProviderExternal(Ljava/lang/String;Landroid/os/IBinder;)V
-Landroid/app/IActivityManager;->removeStack(I)V
-Landroid/app/IActivityManager;->removeTask(I)Z
-Landroid/app/IActivityManager;->requestBugReport(I)V
-Landroid/app/IActivityManager;->resizeDockedStack(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;)V
-Landroid/app/IActivityManager;->resizeStack(ILandroid/graphics/Rect;ZZZI)V
-Landroid/app/IActivityManager;->resizeTask(ILandroid/graphics/Rect;I)V
-Landroid/app/IActivityManager;->restart()V
-Landroid/app/IActivityManager;->resumeAppSwitches()V
-Landroid/app/IActivityManager;->sendIdleJobTrigger()V
 Landroid/app/IActivityManager;->serviceDoneExecuting(Landroid/os/IBinder;III)V
-Landroid/app/IActivityManager;->setActivityController(Landroid/app/IActivityController;Z)V
-Landroid/app/IActivityManager;->setAlwaysFinish(Z)V
-Landroid/app/IActivityManager;->setDebugApp(Ljava/lang/String;ZZ)V
-Landroid/app/IActivityManager;->setDumpHeapDebugLimit(Ljava/lang/String;IJLjava/lang/String;)V
-Landroid/app/IActivityManager;->setPackageScreenCompatMode(Ljava/lang/String;I)V
-Landroid/app/IActivityManager;->setProcessImportant(Landroid/os/IBinder;IZLjava/lang/String;)V
-Landroid/app/IActivityManager;->setProcessLimit(I)V
-Landroid/app/IActivityManager;->setProcessMemoryTrimLevel(Ljava/lang/String;II)Z
-Landroid/app/IActivityManager;->setRequestedOrientation(Landroid/os/IBinder;I)V
-Landroid/app/IActivityManager;->setTaskResizeable(II)V
-Landroid/app/IActivityManager;->shutdown(I)Z
-Landroid/app/IActivityManager;->startActivity(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;)I
-Landroid/app/IActivityManager;->startActivityAsUser(Landroid/app/IApplicationThread;Ljava/lang/String;Landroid/content/Intent;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;IILandroid/app/ProfilerInfo;Landroid/os/Bundle;I)I
-Landroid/app/IActivityManager;->startActivityFromRecents(ILandroid/os/Bundle;)I
-Landroid/app/IActivityManager;->startBinderTracking()Z
-Landroid/app/IActivityManager;->startInstrumentation(Landroid/content/ComponentName;Ljava/lang/String;ILandroid/os/Bundle;Landroid/app/IInstrumentationWatcher;Landroid/app/IUiAutomationConnection;ILjava/lang/String;)Z
-Landroid/app/IActivityManager;->startRecentsActivity(Landroid/content/Intent;Landroid/app/IAssistDataReceiver;Landroid/view/IRecentsAnimationRunner;)V
-Landroid/app/IActivityManager;->startSystemLockTaskMode(I)V
-Landroid/app/IActivityManager;->startUserInBackground(I)Z
-Landroid/app/IActivityManager;->stopAppSwitches()V
-Landroid/app/IActivityManager;->stopBinderTrackingAndDump(Landroid/os/ParcelFileDescriptor;)Z
-Landroid/app/IActivityManager;->stopService(Landroid/app/IApplicationThread;Landroid/content/Intent;Ljava/lang/String;I)I
-Landroid/app/IActivityManager;->stopUser(IZLandroid/app/IStopUserCallback;)I
-Landroid/app/IActivityManager;->suppressResizeConfigChanges(Z)V
-Landroid/app/IActivityManager;->switchUser(I)Z
-Landroid/app/IActivityManager;->unbindService(Landroid/app/IServiceConnection;)Z
-Landroid/app/IActivityManager;->unhandledBack()V
-Landroid/app/IActivityManager;->unlockUser(I[B[BLandroid/os/IProgressListener;)Z
-Landroid/app/IActivityManager;->unregisterProcessObserver(Landroid/app/IProcessObserver;)V
-Landroid/app/IActivityManager;->unregisterReceiver(Landroid/content/IIntentReceiver;)V
-Landroid/app/IActivityManager;->unstableProviderDied(Landroid/os/IBinder;)V
-Landroid/app/IActivityManager;->updateConfiguration(Landroid/content/res/Configuration;)Z
-Landroid/app/IActivityManager;->updatePersistentConfiguration(Landroid/content/res/Configuration;)V
 Landroid/app/IAlarmManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IAlarmManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IAlarmManager;
 Landroid/app/IAlarmManager$Stub;->TRANSACTION_remove:I
 Landroid/app/IAlarmManager$Stub;->TRANSACTION_set:I
-Landroid/app/IAlarmManager;->getNextAlarmClock(I)Landroid/app/AlarmManager$AlarmClockInfo;
-Landroid/app/IAlarmManager;->set(Ljava/lang/String;IJJJILandroid/app/PendingIntent;Landroid/app/IAlarmListener;Ljava/lang/String;Landroid/os/WorkSource;Landroid/app/AlarmManager$AlarmClockInfo;)V
-Landroid/app/IAlarmManager;->setTime(J)Z
-Landroid/app/IApplicationThread;->scheduleBindService(Landroid/os/IBinder;Landroid/content/Intent;ZI)V
-Landroid/app/IApplicationThread;->scheduleCreateService(Landroid/os/IBinder;Landroid/content/pm/ServiceInfo;Landroid/content/res/CompatibilityInfo;I)V
-Landroid/app/IApplicationThread;->scheduleStopService(Landroid/os/IBinder;)V
-Landroid/app/IApplicationThread;->scheduleTrimMemory(I)V
-Landroid/app/IApplicationThread;->scheduleUnbindService(Landroid/os/IBinder;Landroid/content/Intent;)V
-Landroid/app/IAppTask;->getTaskInfo()Landroid/app/ActivityManager$RecentTaskInfo;
 Landroid/app/IAssistDataReceiver$Stub;-><init>()V
-Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V
-Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
 Landroid/app/IInstrumentationWatcher$Stub;-><init>()V
-Landroid/app/IInstrumentationWatcher;->instrumentationStatus(Landroid/content/ComponentName;ILandroid/os/Bundle;)V
 Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/INotificationManager$Stub$Proxy;->areNotificationsEnabledForPackage(Ljava/lang/String;I)Z
 Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
 Landroid/app/INotificationManager$Stub;->TRANSACTION_enqueueNotificationWithTag:I
-Landroid/app/INotificationManager;->areNotificationsEnabledForPackage(Ljava/lang/String;I)Z
-Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
-Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
-Landroid/app/INotificationManager;->cancelToast(Ljava/lang/String;Landroid/app/ITransientNotification;)V
-Landroid/app/INotificationManager;->enqueueToast(Ljava/lang/String;Landroid/app/ITransientNotification;II)V
-Landroid/app/INotificationManager;->getActiveNotifications(Ljava/lang/String;)[Landroid/service/notification/StatusBarNotification;
-Landroid/app/INotificationManager;->getHistoricalNotifications(Ljava/lang/String;I)[Landroid/service/notification/StatusBarNotification;
-Landroid/app/INotificationManager;->getZenMode()I
-Landroid/app/INotificationManager;->getZenModeConfig()Landroid/service/notification/ZenModeConfig;
 Landroid/app/IProcessObserver$Stub;-><init>()V
 Landroid/app/ISearchManager$Stub$Proxy;->getGlobalSearchActivity()Landroid/content/ComponentName;
 Landroid/app/ISearchManager$Stub$Proxy;->getWebSearchActivity()Landroid/content/ComponentName;
 Landroid/app/ISearchManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/ISearchManager;
-Landroid/app/ISearchManager;->getGlobalSearchActivity()Landroid/content/ComponentName;
 Landroid/app/IServiceConnection$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IServiceConnection$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/IServiceConnection$Stub;-><init>()V
 Landroid/app/IServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IServiceConnection;
-Landroid/app/IServiceConnection;->connected(Landroid/content/ComponentName;Landroid/os/IBinder;Z)V
 Landroid/app/IStopUserCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IStopUserCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/IStopUserCallback$Stub;-><init>()V
-Landroid/app/IStopUserCallback;->userStopped(I)V
 Landroid/app/ITransientNotification$Stub;-><init>()V
-Landroid/app/ITransientNotification;->show(Landroid/os/IBinder;)V
 Landroid/app/IUiModeManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/IUserSwitchObserver$Stub;-><init>()V
 Landroid/app/IWallpaperManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/IWallpaperManager;
-Landroid/app/IWallpaperManager;->getHeightHint(I)I
-Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor;
-Landroid/app/IWallpaperManager;->getWallpaperInfo(I)Landroid/app/WallpaperInfo;
-Landroid/app/IWallpaperManager;->getWidthHint(I)I
-Landroid/app/IWallpaperManager;->hasNamedWallpaper(Ljava/lang/String;)Z
-Landroid/app/IWallpaperManager;->setWallpaperComponent(Landroid/content/ComponentName;)V
 Landroid/app/IWallpaperManagerCallback$Stub;-><init>()V
 Landroid/app/job/IJobCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/job/IJobCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/job/IJobCallback$Stub;-><init>()V
 Landroid/app/job/IJobCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobCallback;
-Landroid/app/job/IJobCallback;->acknowledgeStartMessage(IZ)V
-Landroid/app/job/IJobCallback;->acknowledgeStopMessage(IZ)V
-Landroid/app/job/IJobCallback;->completeWork(II)Z
-Landroid/app/job/IJobCallback;->dequeueWork(I)Landroid/app/job/JobWorkItem;
-Landroid/app/job/IJobCallback;->jobFinished(IZ)V
 Landroid/app/job/IJobScheduler$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/job/IJobScheduler$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobScheduler;
 Landroid/app/job/IJobService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/job/IJobService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/job/IJobService$Stub;-><init>()V
 Landroid/app/job/IJobService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobService;
-Landroid/app/job/IJobService;->startJob(Landroid/app/job/JobParameters;)V
-Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
 Landroid/app/PackageDeleteObserver;-><init>()V
 Landroid/app/PackageInstallObserver;-><init>()V
-Landroid/app/ReceiverRestrictedContext;-><init>(Landroid/content/Context;)V
 Landroid/app/ResourcesManager$ActivityResources;-><init>()V
 Landroid/app/ResourcesManager;-><init>()V
 Landroid/app/TaskStackListener;-><init>()V
 Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/UiAutomationConnection;-><init>()V
 Landroid/app/usage/IUsageStatsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/usage/IUsageStatsManager;
-Landroid/app/usage/IUsageStatsManager;->isAppInactive(Ljava/lang/String;I)Z
-Landroid/app/usage/IUsageStatsManager;->queryConfigurationStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
-Landroid/app/usage/IUsageStatsManager;->queryUsageStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
-Landroid/app/usage/IUsageStatsManager;->setAppInactive(Ljava/lang/String;ZI)V
 Landroid/app/UserSwitchObserver;-><init>()V
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
@@ -284,22 +124,14 @@
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
 Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V
-Landroid/content/ContentProviderProxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IContentService$Stub;-><init>()V
 Landroid/content/IContentService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentService;
-Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)V
-Landroid/content/IContentService;->getIsSyncable(Landroid/accounts/Account;Ljava/lang/String;)I
-Landroid/content/IContentService;->getMasterSyncAutomatically()Z
-Landroid/content/IContentService;->getSyncAdapterTypes()[Landroid/content/SyncAdapterType;
-Landroid/content/IContentService;->isSyncActive(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)Z
-Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V
 Landroid/content/IIntentReceiver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IIntentReceiver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/IIntentReceiver$Stub;-><init>()V
-Landroid/content/IIntentReceiver;->performReceive(Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;ZZI)V
 Landroid/content/IOnPrimaryClipChangedListener$Stub;-><init>()V
 Landroid/content/IOnPrimaryClipChangedListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IOnPrimaryClipChangedListener;
 Landroid/content/IRestrictionsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IRestrictionsManager;
@@ -307,29 +139,20 @@
 Landroid/content/ISyncAdapter$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncAdapter$Stub;-><init>()V
 Landroid/content/ISyncAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncAdapter;
-Landroid/content/ISyncAdapter;->cancelSync(Landroid/content/ISyncContext;)V
-Landroid/content/ISyncAdapter;->onUnsyncableAccount(Landroid/content/ISyncAdapterUnsyncableAccountCallback;)V
-Landroid/content/ISyncAdapter;->startSync(Landroid/content/ISyncContext;Ljava/lang/String;Landroid/accounts/Account;Landroid/os/Bundle;)V
 Landroid/content/ISyncContext$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/ISyncContext$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncContext$Stub;-><init>()V
 Landroid/content/ISyncContext$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncContext;
 Landroid/content/ISyncServiceAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncServiceAdapter;
-Landroid/content/ISyncServiceAdapter;->cancelSync(Landroid/content/ISyncContext;)V
-Landroid/content/ISyncServiceAdapter;->startSync(Landroid/content/ISyncContext;Landroid/os/Bundle;)V
 Landroid/content/ISyncStatusObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/ISyncStatusObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncStatusObserver$Stub;-><init>()V
 Landroid/content/ISyncStatusObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncStatusObserver;
-Landroid/content/ISyncStatusObserver;->onStatusChanged(I)V
 Landroid/content/om/IOverlayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/om/IOverlayManager;
-Landroid/content/om/IOverlayManager;->getAllOverlays(I)Ljava/util/Map;
-Landroid/content/om/IOverlayManager;->getOverlayInfo(Ljava/lang/String;I)Landroid/content/om/OverlayInfo;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDataObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
-Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
@@ -337,17 +160,9 @@
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver2;
-Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V
-Landroid/content/pm/IPackageInstaller;->uninstall(Landroid/content/pm/VersionedPackage;Ljava/lang/String;ILandroid/content/IntentSender;I)V
 Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallerCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallerCallback;
-Landroid/content/pm/IPackageInstallerCallback;->onSessionActiveChanged(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionBadgingChanged(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionCreated(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionFinished(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionProgressChanged(IF)V
 Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallerSession$Stub;-><init>()V
@@ -356,8 +171,6 @@
 Landroid/content/pm/IPackageInstallObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallObserver2$Stub;-><init>()V
 Landroid/content/pm/IPackageInstallObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallObserver2;
-Landroid/content/pm/IPackageInstallObserver2;->onPackageInstalled(Ljava/lang/String;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/pm/IPackageInstallObserver2;->onUserActionRequired(Landroid/content/Intent;)V
 Landroid/content/pm/IPackageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageManager$Stub$Proxy;->checkUidPermission(Ljava/lang/String;I)I
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
@@ -369,69 +182,12 @@
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
 Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
 Landroid/content/pm/IPackageManager$Stub;->TRANSACTION_getApplicationInfo:I
-Landroid/content/pm/IPackageManager;->addPermission(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->addPermissionAsync(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->canonicalToCurrentPackageNames([Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->checkPermission(Ljava/lang/String;Ljava/lang/String;I)I
-Landroid/content/pm/IPackageManager;->checkSignatures(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->checkUidSignatures(II)I
-Landroid/content/pm/IPackageManager;->clearPackagePreferredActivities(Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->currentToCanonicalPackageNames([Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->deleteApplicationCacheFiles(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getApplicationEnabledSetting(Ljava/lang/String;I)I
-Landroid/content/pm/IPackageManager;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/IPackageManager;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getBlockUninstallForUser(Ljava/lang/String;I)Z
-Landroid/content/pm/IPackageManager;->getComponentEnabledSetting(Landroid/content/ComponentName;I)I
-Landroid/content/pm/IPackageManager;->getFlagsForUid(I)I
-Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/content/pm/IPackageManager;->getInstalledApplications(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->getInstallerPackageName(Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getInstallLocation()I
-Landroid/content/pm/IPackageManager;->getInstrumentationInfo(Landroid/content/ComponentName;I)Landroid/content/pm/InstrumentationInfo;
-Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager;->getNameForUid(I)Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/IPackageManager;->getPackageInstaller()Landroid/content/pm/IPackageInstaller;
-Landroid/content/pm/IPackageManager;->getPackagesForUid(I)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPackageUid(Ljava/lang/String;II)I
-Landroid/content/pm/IPackageManager;->getPermissionControllerPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPermissionGroupInfo(Ljava/lang/String;I)Landroid/content/pm/PermissionGroupInfo;
-Landroid/content/pm/IPackageManager;->getPreferredActivities(Ljava/util/List;Ljava/util/List;Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->getProviderInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/IPackageManager;->getReceiverInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getServiceInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ServiceInfo;
-Landroid/content/pm/IPackageManager;->getServicesSystemSharedLibraryPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getSharedSystemSharedLibraryPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getSystemSharedLibraryNames()[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getUidForSharedUser(Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->grantRuntimePermission(Ljava/lang/String;Ljava/lang/String;I)V
-Landroid/content/pm/IPackageManager;->hasSystemUidErrors()Z
-Landroid/content/pm/IPackageManager;->isPackageAvailable(Ljava/lang/String;I)Z
-Landroid/content/pm/IPackageManager;->isSafeMode()Z
-Landroid/content/pm/IPackageManager;->isStorageLow()Z
-Landroid/content/pm/IPackageManager;->isUidPrivileged(I)Z
-Landroid/content/pm/IPackageManager;->queryInstrumentation(Ljava/lang/String;I)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->queryIntentActivities(Landroid/content/Intent;Ljava/lang/String;II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->querySyncProviders(Ljava/util/List;Ljava/util/List;)V
-Landroid/content/pm/IPackageManager;->removePermission(Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->replacePreferredActivity(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;I)V
-Landroid/content/pm/IPackageManager;->resolveIntent(Landroid/content/Intent;Ljava/lang/String;II)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setApplicationHiddenSettingAsUser(Ljava/lang/String;ZI)Z
-Landroid/content/pm/IPackageManager;->setComponentEnabledSetting(Landroid/content/ComponentName;III)V
-Landroid/content/pm/IPackageManager;->setInstallerPackageName(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V
-Landroid/content/pm/IPackageManager;->setPackageStoppedState(Ljava/lang/String;ZI)V
 Landroid/content/pm/IPackageMoveObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageMoveObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageMoveObserver;
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
-Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
 Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
 Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
@@ -1519,7 +1275,7 @@
 Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType;
 Lcom/android/internal/os/BinderInternal;->getContextObject()Landroid/os/IBinder;
 Lcom/android/internal/os/BinderInternal;->handleGc()V
-Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;
+Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I
@@ -3041,7 +2797,6 @@
 Lcom/android/internal/telephony/ServiceStateTracker;->isInvalidOperatorNumeric(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ServiceStateTracker;->log(Ljava/lang/String;)V
 Lcom/android/internal/telephony/ServiceStateTracker;->loge(Ljava/lang/String;)V
-Lcom/android/internal/telephony/ServiceStateTracker;->mAttachedRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/ServiceStateTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
 Lcom/android/internal/telephony/ServiceStateTracker;->mCr:Landroid/content/ContentResolver;
 Lcom/android/internal/telephony/ServiceStateTracker;->mCurDataSpn:Ljava/lang/String;
@@ -3053,7 +2808,6 @@
 Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOnRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/ServiceStateTracker;->mDefaultRoamingIndicator:I
 Lcom/android/internal/telephony/ServiceStateTracker;->mDesiredPowerState:Z
-Lcom/android/internal/telephony/ServiceStateTracker;->mDetachedRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/ServiceStateTracker;->mDeviceShuttingDown:Z
 Lcom/android/internal/telephony/ServiceStateTracker;->mEmergencyOnly:Z
 Lcom/android/internal/telephony/ServiceStateTracker;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
@@ -3081,7 +2835,6 @@
 Lcom/android/internal/telephony/ServiceStateTracker;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
 Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOffRegistrants:Landroid/os/RegistrantList;
 Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants:Landroid/os/RegistrantList;
-Lcom/android/internal/telephony/ServiceStateTracker;->notifyDataRegStateRilRadioTechnologyChanged()V
 Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z
 Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V
 Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V
diff --git a/core/java/android/accounts/IAccountAuthenticator.aidl b/core/java/android/accounts/IAccountAuthenticator.aidl
index 8b98ca2..701cecf 100644
--- a/core/java/android/accounts/IAccountAuthenticator.aidl
+++ b/core/java/android/accounts/IAccountAuthenticator.aidl
@@ -28,47 +28,55 @@
     /**
      * prompts the user for account information and adds the result to the IAccountManager
      */
+    @UnsupportedAppUsage
     void addAccount(in IAccountAuthenticatorResponse response, String accountType,
         String authTokenType, in String[] requiredFeatures, in Bundle options);
 
     /**
      * prompts the user for the credentials of the account
      */
+    @UnsupportedAppUsage
     void confirmCredentials(in IAccountAuthenticatorResponse response, in Account account,
         in Bundle options);
 
     /**
      * gets the password by either prompting the user or querying the IAccountManager
      */
+    @UnsupportedAppUsage
     void getAuthToken(in IAccountAuthenticatorResponse response, in Account account,
         String authTokenType, in Bundle options);
 
     /**
      * Gets the user-visible label of the given authtoken type.
      */
+    @UnsupportedAppUsage
     void getAuthTokenLabel(in IAccountAuthenticatorResponse response, String authTokenType);
 
     /**
      * prompts the user for a new password and writes it to the IAccountManager
      */
+    @UnsupportedAppUsage
     void updateCredentials(in IAccountAuthenticatorResponse response, in Account account,
         String authTokenType, in Bundle options);
 
     /**
      * launches an activity that lets the user edit and set the properties for an authenticator
      */
+    @UnsupportedAppUsage
     void editProperties(in IAccountAuthenticatorResponse response, String accountType);
 
     /**
      * returns a Bundle where the boolean value BOOLEAN_RESULT_KEY is set if the account has the
      * specified features
      */
+    @UnsupportedAppUsage
     void hasFeatures(in IAccountAuthenticatorResponse response, in Account account, 
         in String[] features);
 
     /**
      * Gets whether or not the account is allowed to be removed.
      */
+    @UnsupportedAppUsage
     void getAccountRemovalAllowed(in IAccountAuthenticatorResponse response, in Account account);
 
     /**
diff --git a/core/java/android/accounts/IAccountAuthenticatorResponse.aidl b/core/java/android/accounts/IAccountAuthenticatorResponse.aidl
index 0c75e50..fbc8e5d 100644
--- a/core/java/android/accounts/IAccountAuthenticatorResponse.aidl
+++ b/core/java/android/accounts/IAccountAuthenticatorResponse.aidl
@@ -22,7 +22,10 @@
  * @hide
  */
 oneway interface IAccountAuthenticatorResponse {
+    @UnsupportedAppUsage
     void onResult(in Bundle value);
+    @UnsupportedAppUsage
     void onRequestContinued();
+    @UnsupportedAppUsage
     void onError(int errorCode, String errorMessage);
 }
diff --git a/core/java/android/accounts/IAccountManagerResponse.aidl b/core/java/android/accounts/IAccountManagerResponse.aidl
index ca1203d..11d0c02 100644
--- a/core/java/android/accounts/IAccountManagerResponse.aidl
+++ b/core/java/android/accounts/IAccountManagerResponse.aidl
@@ -22,6 +22,8 @@
  * @hide
  */
 oneway interface IAccountManagerResponse {
+    @UnsupportedAppUsage
     void onResult(in Bundle value);
+    @UnsupportedAppUsage
     void onError(int errorCode, String errorMessage);
 }
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 831cac2..e573279 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -36,6 +36,7 @@
 import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
 import android.view.Window;
+import android.view.inspector.InspectableProperty;
 import android.widget.SpinnerAdapter;
 
 import java.lang.annotation.Retention;
@@ -1374,6 +1375,9 @@
                 @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
                 @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
         })
+        @InspectableProperty(
+                name = "layout_gravity",
+                valueType = InspectableProperty.ValueType.GRAVITY)
         public int gravity = Gravity.NO_GRAVITY;
 
         public LayoutParams(@NonNull Context c, AttributeSet attrs) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 68b2de4..56bf8fa 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,6 +127,7 @@
 import android.view.autofill.IAutofillWindowPresenter;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -717,7 +718,7 @@
         Window.Callback, KeyEvent.Callback,
         OnCreateContextMenuListener, ComponentCallbacks2,
         Window.OnWindowDismissedCallback, WindowControllerCallback,
-        AutofillManager.AutofillClient {
+        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
     private static final String TAG = "Activity";
     private static final boolean DEBUG_LIFECYCLE = false;
 
@@ -1119,6 +1120,12 @@
         return this;
     }
 
+    /** @hide */
+    @Override
+    public final ContentCaptureClient getContentCaptureClient() {
+        return this;
+    }
+
     /**
      * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
      * lifecycle callbacks for only this Activity.
@@ -6464,6 +6471,12 @@
         return getComponentName();
     }
 
+    /** @hide */
+    @Override
+    public final ComponentName contentCaptureClientGetComponentName() {
+        return getComponentName();
+    }
+
     /**
      * Retrieve a {@link SharedPreferences} object for accessing preferences
      * that are private to this activity.  This simply calls the underlying
@@ -8366,11 +8379,8 @@
      *                              screen when this activity has another activity behind it with
      *                              the showWhenLock attribute set; {@code false} otherwise.
      * @see #setShowWhenLocked(boolean)
-     * See android.R.attr#inheritShowWhenLocked
-     * @hide
+     * @see android.R.attr#inheritShowWhenLocked
      */
-    @SystemApi
-    @TestApi
     public void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
         try {
             ActivityTaskManager.getService().setInheritShowWhenLocked(
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 7d828d8..664f0a3 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -196,6 +196,9 @@
     /** Kill the processes in the list due to their tasks been removed. */
     public abstract void killProcessesForRemovedTask(ArrayList<Object> procsToKill);
 
+    /** Kill the process immediately. */
+    public abstract void killProcess(String processName, int uid, String reason);
+
     /**
      * Returns {@code true} if {@code uid} is running an activity from {@code packageName}.
      */
@@ -276,6 +279,7 @@
     public abstract boolean isActivityStartsLoggingEnabled();
     /** Returns true if the background activity starts is enabled. */
     public abstract boolean isBackgroundActivityStartsEnabled();
+    public abstract boolean isPackageNameWhitelistedForBgActivityStarts(String packageName);
     public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing);
 
     /** Input dispatch timeout to a window, start the ANR process. */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b654258..c0a702f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -332,7 +332,6 @@
     String[] mInstrumentedSplitAppDirs = null;
     String mInstrumentedLibDir = null;
     boolean mSystemThread = false;
-    boolean mJitEnabled = false;
     boolean mSomeActivitiesChanged = false;
     boolean mUpdatingSystemConfig = false;
     /* package */ boolean mHiddenApiWarningShown = false;
@@ -1696,7 +1695,6 @@
         public static final int SUICIDE                 = 130;
         @UnsupportedAppUsage
         public static final int REMOVE_PROVIDER         = 131;
-        public static final int ENABLE_JIT              = 132;
         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
         @UnsupportedAppUsage
         public static final int SCHEDULE_CRASH          = 134;
@@ -1746,7 +1744,6 @@
                     case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
                     case SUICIDE: return "SUICIDE";
                     case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
-                    case ENABLE_JIT: return "ENABLE_JIT";
                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                     case DUMP_HEAP: return "DUMP_HEAP";
@@ -1858,9 +1855,6 @@
                     completeRemoveProvider((ProviderRefCount)msg.obj);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
-                case ENABLE_JIT:
-                    ensureJitEnabled();
-                    break;
                 case DISPATCH_PACKAGE_BROADCAST:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
@@ -1996,7 +1990,6 @@
             if (stopProfiling) {
                 mProfiler.stopProfiling();
             }
-            ensureJitEnabled();
             return false;
         }
     }
@@ -2330,13 +2323,6 @@
         }
     }
 
-    void ensureJitEnabled() {
-        if (!mJitEnabled) {
-            mJitEnabled = true;
-            dalvik.system.VMRuntime.getRuntime().startJitCompilation();
-        }
-    }
-
     @UnsupportedAppUsage
     void scheduleGcIdler() {
         if (!mGcIdlerScheduled) {
@@ -3129,10 +3115,6 @@
         if (!r.stopped) {
             throw new IllegalStateException("Can't start activity that is not stopped.");
         }
-        if (r.activity.mFinished) {
-            // TODO(lifecycler): How can this happen?
-            return;
-        }
 
         // Start
         activity.performStart("handleStartActivity");
@@ -3255,6 +3237,8 @@
             if (!r.activity.mFinished && pendingActions != null) {
                 pendingActions.setOldState(r.state);
                 pendingActions.setRestoreInstanceState(true);
+            }
+            if (pendingActions != null) {
                 pendingActions.setCallOnPostCreate(true);
             }
         } else {
@@ -3782,7 +3766,6 @@
                         ActivityManager.getService().serviceDoneExecuting(
                                 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                     }
-                    ensureJitEnabled();
                 } catch (RemoteException ex) {
                     throw ex.rethrowFromSystemServer();
                 }
@@ -3896,7 +3879,6 @@
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
                 }
-                ensureJitEnabled();
             } catch (Exception e) {
                 if (!mInstrumentation.onException(s, e)) {
                     throw new RuntimeException(
@@ -3958,7 +3940,7 @@
         if (localLOGV) {
             Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
         }
-        if (r == null || r.activity.mFinished) {
+        if (r == null) {
             return null;
         }
         if (r.getLifecycleState() == ON_RESUME) {
@@ -4228,12 +4210,6 @@
     private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
             PendingTransactionActions pendingActions) {
         if (r.paused) {
-            if (r.activity.mFinished) {
-                // If we are finishing, we won't call onResume() in certain cases.
-                // So here we likewise don't want to call onPause() if the activity
-                // isn't resumed.
-                return null;
-            }
             RuntimeException e = new RuntimeException(
                     "Performing pause of activity that is not resumed: "
                     + r.intent.getComponent().toShortString());
@@ -4353,20 +4329,13 @@
             boolean saveState, boolean finalStateRequest, String reason) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
         if (r != null) {
-            if (!keepShown && r.stopped) {
-                if (r.activity.mFinished) {
-                    // If we are finishing, we won't call onResume() in certain
-                    // cases.  So here we likewise don't want to call onStop()
-                    // if the activity isn't resumed.
-                    return;
-                }
-                if (!finalStateRequest) {
-                    final RuntimeException e = new RuntimeException(
-                            "Performing stop of activity that is already stopped: "
-                                    + r.intent.getComponent().toShortString());
-                    Slog.e(TAG, e.getMessage(), e);
-                    Slog.e(TAG, r.getStateString());
-                }
+            if (!keepShown && r.stopped && !finalStateRequest) {
+                // Double stop request is possible if activity receives 'sleep' followed by 'stop'.
+                final RuntimeException e = new RuntimeException(
+                        "Performing stop of activity that is already stopped: "
+                                + r.intent.getComponent().toShortString());
+                Slog.e(TAG, e.getMessage(), e);
+                Slog.e(TAG, r.getStateString());
             }
 
             // One must first be paused before stopped...
@@ -6177,9 +6146,6 @@
             if (!data.restrictedBackupMode) {
                 if (!ArrayUtils.isEmpty(data.providers)) {
                     installContentProviders(app, data.providers);
-                    // For process that contains content providers, we want to
-                    // ensure that the JIT is enabled "at some point".
-                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                 }
             }
 
@@ -6812,12 +6778,6 @@
         sCurrentActivityThread = this;
         mSystemThread = system;
         if (!system) {
-            ViewRootImpl.addFirstDrawHandler(new Runnable() {
-                @Override
-                public void run() {
-                    ensureJitEnabled();
-                }
-            });
             android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                     UserHandle.myUserId());
             RuntimeInit.setApplicationObject(mAppThread.asBinder());
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 5bf7ef5..91df05f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -43,6 +43,8 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.ArrayMap;
+import android.util.LongSparseArray;
+import android.util.LongSparseLongArray;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -55,8 +57,10 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.ArrayList;
@@ -64,9 +68,11 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 /**
  * API for interacting with "application operation" tracking.
@@ -227,7 +233,7 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, prefix = { "UID_STATE_" }, value = {
+    @IntDef(prefix = { "UID_STATE_" }, value = {
             UID_STATE_PERSISTENT,
             UID_STATE_TOP,
             UID_STATE_FOREGROUND_SERVICE_LOCATION,
@@ -239,78 +245,322 @@
     public @interface UidState {}
 
     /**
-     * Invalid UID state.
-     * @hide
-     */
-    public static final int UID_STATE_INVALID = -1;
-
-    /**
-     * Metrics about an op when its uid is persistent.
+     * Uid state: The UID is a foreground persistent app.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_PERSISTENT = 0;
+    public static final int UID_STATE_PERSISTENT = 100;
 
     /**
-     * Metrics about an op when its uid is at the top.
+     * Uid state: The UID is top foreground app.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_TOP = 1;
+    public static final int UID_STATE_TOP = 200;
 
     /**
-     * Metrics about an op when its uid is running a foreground service with location type.
+     * Uid state: The UID is running a foreground service of location type.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 2;
+    public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300;
 
     /**
-     * Metrics about an op when its uid is running a foreground service.
+     * Uid state: The UID is running a foreground service.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_FOREGROUND_SERVICE = 3;
+    public static final int UID_STATE_FOREGROUND_SERVICE = 400;
 
     /**
-     * Last UID state in which we don't restrict what an op can do.
+     * The max, which is min priority, UID state for which any app op
+     * would be considered as performed in the foreground.
      * @hide
      */
-    public static final int UID_STATE_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE_LOCATION;
+    public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE;
 
     /**
-     * Metrics about an op when its uid is in the foreground for any other reasons.
+     * Uid state: The UID is a foreground app.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_FOREGROUND = 4;
+    public static final int UID_STATE_FOREGROUND = 500;
 
     /**
-     * Metrics about an op when its uid is in the background for any reason.
+     * Uid state: The UID is a background app.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_BACKGROUND = 5;
+    public static final int UID_STATE_BACKGROUND = 600;
 
     /**
-     * Metrics about an op when its uid is cached.
+     * Uid state: The UID is a cached app.
      * @hide
      */
     @TestApi
     @SystemApi
-    public static final int UID_STATE_CACHED = 6;
+    public static final int UID_STATE_CACHED = 700;
 
     /**
-     * Number of uid states we track.
+     * Uid state: The UID state with the highest priority.
      * @hide
      */
-    public static final int _NUM_UID_STATE = 7;
+    public static final int MAX_PRIORITY_UID_STATE = UID_STATE_PERSISTENT;
+
+    /**
+     * Uid state: The UID state with the lowest priority.
+     * @hide
+     */
+    public static final int MIN_PRIORITY_UID_STATE = UID_STATE_CACHED;
+
+    /**
+     * Resolves the first unrestricted state given an app op. Location is
+     * special as we want to allow its access only if a dedicated location
+     * foreground service is running. For other ops we consider any foreground
+     * service as a foreground state.
+     *
+     * @param op The op to resolve.
+     * @return The last restricted UID state.
+     *
+     * @hide
+     */
+    public static int resolveFirstUnrestrictedUidState(int op) {
+        switch (op) {
+            case OP_FINE_LOCATION:
+            case OP_COARSE_LOCATION: {
+                return UID_STATE_FOREGROUND_SERVICE_LOCATION;
+            }
+        }
+        return UID_STATE_FOREGROUND_SERVICE;
+    }
+
+    /**
+     * Resolves the last restricted state given an app op. Location is
+     * special as we want to allow its access only if a dedicated location
+     * foreground service is running. For other ops we consider any foreground
+     * service as a foreground state.
+     *
+     * @param op The op to resolve.
+     * @return The last restricted UID state.
+     *
+     * @hide
+     */
+    public static int resolveLastRestrictedUidState(int op) {
+        switch (op) {
+            case OP_FINE_LOCATION:
+            case OP_COARSE_LOCATION: {
+                return UID_STATE_FOREGROUND_SERVICE;
+            }
+        }
+        return UID_STATE_FOREGROUND;
+    }
+
+    /** @hide Note: Keep these sorted */
+    public static final int[] UID_STATES = {
+            UID_STATE_PERSISTENT,
+            UID_STATE_TOP,
+            UID_STATE_FOREGROUND_SERVICE_LOCATION,
+            UID_STATE_FOREGROUND_SERVICE,
+            UID_STATE_FOREGROUND,
+            UID_STATE_BACKGROUND,
+            UID_STATE_CACHED
+    };
+
+    /** @hide */
+    public static String getUidStateName(@UidState int uidState) {
+        switch (uidState) {
+            case UID_STATE_PERSISTENT:
+                return "pers";
+            case UID_STATE_TOP:
+                return "top";
+            case UID_STATE_FOREGROUND_SERVICE_LOCATION:
+                return "fgsvcl";
+            case UID_STATE_FOREGROUND_SERVICE:
+                return "fgsvc";
+            case UID_STATE_FOREGROUND:
+                return "fg";
+            case UID_STATE_BACKGROUND:
+                return "bg";
+            case UID_STATE_CACHED:
+                return "cch";
+            default:
+                return "unknown";
+        }
+    }
+
+    /**
+     * Flag: non proxy operations. These are operations
+     * performed on behalf of the app itself and not on behalf of
+     * another one.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAG_SELF = 0x1;
+
+    /**
+     * Flag: trusted proxy operations. These are operations
+     * performed on behalf of another app by a trusted app.
+     * Which is work a trusted app blames on another app.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAG_TRUSTED_PROXY = 0x2;
+
+    /**
+     * Flag: untrusted proxy operations. These are operations
+     * performed on behalf of another app by an untrusted app.
+     * Which is work an untrusted app blames on another app.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAG_UNTRUSTED_PROXY = 0x4;
+
+    /**
+     * Flag: trusted proxied operations. These are operations
+     * performed by a trusted other app on behalf of an app.
+     * Which is work an app was blamed for by a trusted app.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAG_TRUSTED_PROXIED = 0x8;
+
+    /**
+     * Flag: untrusted proxied operations. These are operations
+     * performed by an untrusted other app on behalf of an app.
+     * Which is work an app was blamed for by an untrusted app.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAG_UNTRUSTED_PROXIED = 0x10;
+
+    /**
+     * Flags: all operations. These include operations matched
+     * by {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXIED},
+     * {@link #OP_FLAG_UNTRUSTED_PROXIED}, {@link #OP_FLAG_TRUSTED_PROXIED},
+     * {@link #OP_FLAG_UNTRUSTED_PROXIED}.
+     *
+     * @hide
+     */
+    @TestApi
+    @SystemApi
+    public static final int OP_FLAGS_ALL =
+            OP_FLAG_SELF
+                | OP_FLAG_TRUSTED_PROXY
+                | OP_FLAG_UNTRUSTED_PROXY
+                | OP_FLAG_TRUSTED_PROXIED
+                | OP_FLAG_UNTRUSTED_PROXIED;
+
+    /**
+     * Flags: all trusted operations which is ones either the app did {@link #OP_FLAG_SELF},
+     * or it was blamed for by a trusted app {@link #OP_FLAG_TRUSTED_PROXIED}, or ones the
+     * app if untrusted blamed on other apps {@link #OP_FLAG_UNTRUSTED_PROXY}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int OP_FLAGS_ALL_TRUSTED = AppOpsManager.OP_FLAG_SELF
+        | AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
+        | AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            OP_FLAG_SELF,
+            OP_FLAG_TRUSTED_PROXY,
+            OP_FLAG_UNTRUSTED_PROXY,
+            OP_FLAG_TRUSTED_PROXIED,
+            OP_FLAG_UNTRUSTED_PROXIED
+    })
+    public @interface OpFlags {}
+
+
+    /** @hide */
+    public static final String getFlagName(@OpFlags int flag) {
+        switch (flag) {
+            case OP_FLAG_SELF:
+                return "s";
+            case OP_FLAG_TRUSTED_PROXY:
+                return "tp";
+            case OP_FLAG_UNTRUSTED_PROXY:
+                return "up";
+            case OP_FLAG_TRUSTED_PROXIED:
+                return "tpd";
+            case OP_FLAG_UNTRUSTED_PROXIED:
+                return "upd";
+            default:
+                return "unknown";
+        }
+    }
+
+    private static final int UID_STATE_OFFSET = 31;
+    private static final int FLAGS_MASK = 0xFFFFFFFF;
+
+    /**
+     * Key for a data bucket storing app op state. The bucket
+     * is composed of the uid state and state flags. This way
+     * we can query data for given uid state and a set of flags where
+     * the flags control which type of data to get. For example,
+     * one can get the ops an app did on behalf of other apps
+     * while in the background.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
+    public @interface DataBucketKey {
+    }
+
+    /** @hide */
+    public static String keyToString(@DataBucketKey long key) {
+        final int uidState = extractUidStateFromKey(key);
+        final int flags = extractFlagsFromKey(key);
+        return "[" + getUidStateName(uidState) + "-" + flagsToString(flags) + "]";
+    }
+
+    /** @hide */
+    public static @DataBucketKey long makeKey(@UidState int uidState, @OpFlags int flags) {
+        return ((long) uidState << UID_STATE_OFFSET) | flags;
+    }
+
+    /** @hide */
+    public static int extractUidStateFromKey(@DataBucketKey long key) {
+        return (int) (key >> UID_STATE_OFFSET);
+    }
+
+    /** @hide */
+    public static int extractFlagsFromKey(@DataBucketKey long key) {
+        return (int) (key & FLAGS_MASK);
+    }
+
+    /** @hide */
+    public static String flagsToString(@OpFlags int flags) {
+        final StringBuilder flagsBuilder = new StringBuilder();
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            if (flagsBuilder.length() > 0) {
+                flagsBuilder.append('|');
+            }
+            flagsBuilder.append(getFlagName(flag));
+        }
+        return flagsBuilder.toString();
+    }
 
     // when adding one of these:
     //  - increment _NUM_OP
@@ -551,7 +801,7 @@
     @UnsupportedAppUsage
     public static final int OP_MANAGE_IPSEC_TUNNELS = 75;
     /** @hide Any app start foreground service. */
-    @UnsupportedAppUsage
+    @TestApi
     public static final int OP_START_FOREGROUND = 76;
     /** @hide */
     @UnsupportedAppUsage
@@ -1947,14 +2197,23 @@
             mEntries = entries;
         }
 
-        public String getPackageName() {
+        /**
+         * @return The name of the package.
+         */
+        public @NonNull String getPackageName() {
             return mPackageName;
         }
 
+        /**
+         * @return The uid of the package.
+         */
         public int getUid() {
             return mUid;
         }
 
+        /**
+         * @return The ops of the package.
+         */
         public List<OpEntry> getOps() {
             return mEntries;
         }
@@ -1999,57 +2258,59 @@
      * Class holding the information about one unique operation of an application.
      * @hide
      */
+    @TestApi
+    @Immutable
     @SystemApi
     public static final class OpEntry implements Parcelable {
         private final int mOp;
-        private final @Mode int mMode;
-        private final long[] mTimes;
-        private final long[] mRejectTimes;
-        private final int mDuration;
-        private final int mProxyUid;
         private final boolean mRunning;
-        private final String mProxyPackageName;
+        private final @Mode int mMode;
+        private final @Nullable LongSparseLongArray mAccessTimes;
+        private final @Nullable LongSparseLongArray mRejectTimes;
+        private final @Nullable LongSparseLongArray mDurations;
+        private final @Nullable LongSparseLongArray mProxyUids;
+        private final @Nullable LongSparseArray<String> mProxyPackageNames;
 
         /**
          * @hide
          */
-        public OpEntry(int op, @Mode int mode, long time, long rejectTime, int duration,
-                int proxyUid, String proxyPackage) {
+        public OpEntry(int op, boolean running, @Mode int mode,
+                @Nullable LongSparseLongArray accessTimes, @Nullable LongSparseLongArray rejectTimes,
+                @Nullable LongSparseLongArray durations, @Nullable LongSparseLongArray proxyUids,
+                @Nullable LongSparseArray<String> proxyPackageNames) {
             mOp = op;
-            mMode = mode;
-            mTimes = new long[_NUM_UID_STATE];
-            mRejectTimes = new long[_NUM_UID_STATE];
-            mTimes[0] = time;
-            mRejectTimes[0] = rejectTime;
-            mDuration = duration;
-            mRunning = duration == -1;
-            mProxyUid = proxyUid;
-            mProxyPackageName = proxyPackage;
-        }
-
-        /**
-         * @hide
-         */
-        public OpEntry(int op, @Mode int mode, long[] times, long[] rejectTimes, int duration,
-                boolean running, int proxyUid, String proxyPackage) {
-            mOp = op;
-            mMode = mode;
-            mTimes = new long[_NUM_UID_STATE];
-            mRejectTimes = new long[_NUM_UID_STATE];
-            System.arraycopy(times, 0, mTimes, 0, _NUM_UID_STATE);
-            System.arraycopy(rejectTimes, 0, mRejectTimes, 0, _NUM_UID_STATE);
-            mDuration = duration;
             mRunning = running;
-            mProxyUid = proxyUid;
-            mProxyPackageName = proxyPackage;
+            mMode = mode;
+            mAccessTimes = accessTimes;
+            mRejectTimes = rejectTimes;
+            mDurations = durations;
+            mProxyUids = proxyUids;
+            mProxyPackageNames = proxyPackageNames;
         }
 
         /**
          * @hide
          */
-        public OpEntry(int op, @Mode int mode, long[] times, long[] rejectTimes, int duration,
-                int proxyUid, String proxyPackage) {
-            this(op, mode, times, rejectTimes, duration, duration == -1, proxyUid, proxyPackage);
+        public OpEntry(int op, @Mode int mode) {
+            mOp = op;
+            mMode = mode;
+            mRunning = false;
+            mAccessTimes = null;
+            mRejectTimes = null;
+            mDurations = null;
+            mProxyUids = null;
+            mProxyPackageNames = null;
+        }
+
+        /**
+         * Returns all keys for which we have mapped state in any of the data buckets -
+         * access time, reject time, duration.
+         * @hide */
+        public @Nullable LongSparseArray<Object> collectKeys() {
+            LongSparseArray<Object> result = AppOpsManager.collectKeys(mAccessTimes, null);
+            result = AppOpsManager.collectKeys(mRejectTimes, result);
+            result = AppOpsManager.collectKeys(mDurations, result);
+            return result;
         }
 
         /**
@@ -2061,14 +2322,14 @@
         }
 
         /**
-         * Return this entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
+         * @return This entry's op string name, such as {@link #OPSTR_COARSE_LOCATION}.
          */
-        public String getOpStr() {
+        public @NonNull String getOpStr() {
             return sOpToString[mOp];
         }
 
         /**
-         * Return this entry's current mode, such as {@link #MODE_ALLOWED}.
+         * @return this entry's current mode, such as {@link #MODE_ALLOWED}.
          */
         public @Mode int getMode() {
             return mMode;
@@ -2079,89 +2340,331 @@
          */
         @UnsupportedAppUsage
         public long getTime() {
-            return maxTime(mTimes, 0, _NUM_UID_STATE);
+            return getLastAccessTime(OP_FLAGS_ALL);
         }
 
         /**
-         * Return the last wall clock time this op was accessed by the app.
+         * Return the last wall clock time in milliseconds this op was accessed.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int, int, int)
          */
-        public long getLastAccessTime() {
-            return maxTime(mTimes, 0, _NUM_UID_STATE);
+        public long getLastAccessTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * Return the last wall clock time this op was accessed by the app while in the foreground.
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the foreground.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
          */
-        public long getLastAccessForegroundTime() {
-            return maxTime(mTimes, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1);
+        public long getLastAccessForegroundTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mAccessTimes, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
         }
 
         /**
-         * Return the last wall clock time this op was accessed by the app while in the background.
+         * Return the last wall clock time in milliseconds this op was accessed
+         * by the app while in the background.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessTime(int)
+         * @see #getLastAccessTime(int, int, int)
          */
-        public long getLastAccessBackgroundTime() {
-            return maxTime(mTimes, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE);
+        public long getLastAccessBackgroundTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mAccessTimes, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * @hide
+         * Return the last wall clock time  in milliseconds this op was accessed
+         * by the app for a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastAccessForegroundTime(int)
+         * @see #getLastAccessBackgroundTime(int)
+         * @see #getLastAccessTime(int)
          */
-        public long getLastTimeFor(int uidState) {
-            return mTimes[uidState];
+        public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return maxForFlagsInStates(mAccessTimes, fromUidState, toUidState, flags);
         }
 
         /**
          * @hide
          */
         public long getRejectTime() {
-            return maxTime(mRejectTimes, 0, _NUM_UID_STATE);
+            return getLastRejectTime(OP_FLAGS_ALL);
         }
 
         /**
-         * Return the last wall clock time the app made an attempt to access this op but
-         * was rejected.
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
          */
-        public long getLastRejectTime() {
-            return maxTime(mRejectTimes, 0, _NUM_UID_STATE);
+        public long getLastRejectTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * Return the last wall clock time the app made an attempt to access this op while in
-         * the foreground but was rejected.
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the foreground but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
          */
-        public long getLastRejectForegroundTime() {
-            return maxTime(mRejectTimes, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1);
+        public long getLastRejectForegroundTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mRejectTimes, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
         }
 
         /**
-         * Return the last wall clock time the app made an attempt to access this op while in
-         * the background but was rejected.
+         * Return the last wall clock time in milliseconds the app made an attempt
+         * to access this op while in the background but was rejected.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last background reject time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectTime(int, int, int)
+         * @see #getLastRejectTime(int)
          */
-        public long getLastRejectBackgroundTime() {
-            return maxTime(mRejectTimes, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE);
+        public long getLastRejectBackgroundTime(@OpFlags int flags) {
+            return maxForFlagsInStates(mRejectTimes, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * @hide
+         * Return the last wall clock time state in milliseconds the app made an
+         * attempt to access this op for a given range of UID states.
+         *
+         * @param fromUidState The UID state from which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state to which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the last foreground access time in milliseconds since
+         * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian).
+         *
+         * @see #getLastRejectForegroundTime(int)
+         * @see #getLastRejectBackgroundTime(int)
+         * @see #getLastRejectTime(int)
          */
-        public long getLastRejectTimeFor(int uidState) {
-            return mRejectTimes[uidState];
+        public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return maxForFlagsInStates(mRejectTimes, fromUidState, toUidState, flags);
         }
 
+        /**
+         * @return Whether the operation is running.
+         */
         public boolean isRunning() {
             return mRunning;
         }
 
-        public int getDuration() {
-            return mDuration;
+        /**
+         * @return The duration of the operation in milliseconds.
+         */
+        public long getDuration() {
+            return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
         }
 
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the foreground.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the foreground access duration in milliseconds.
+         *
+         * @see #getLastBackgroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastForegroundDuration(@OpFlags int flags) {
+            return sumForFlagsInStates(mDurations, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op while
+         * in the background.
+         *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the background access duration in milliseconds.
+         *
+         * @see #getLastForegroundDuration(int)
+         * @see #getLastDuration(int, int, int)
+         */
+        public long getLastBackgroundDuration(@OpFlags int flags) {
+            return sumForFlagsInStates(mDurations, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
+        }
+
+        /**
+         * Return the duration in milliseconds the app accessed this op for
+         * a given range of UID states.
+         *
+         * @param fromUidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state for which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return the access duration in milliseconds.
+         */
+        public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return sumForFlagsInStates(mDurations, fromUidState, toUidState, flags);
+        }
+
+        /**
+         * Gets the UID of the app that performed the op on behalf of this app and
+         * as a result blamed the op on this app or {@link Process#INVALID_UID} if
+         * there is no proxy.
+         *
+         * @return The proxy UID.
+         */
         public int getProxyUid() {
-            return  mProxyUid;
+            return (int) findFirstNonNegativeForFlagsInStates(mDurations,
+                    MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
         }
 
-        public String getProxyPackageName() {
-            return mProxyPackageName;
+        /**
+         * Gets the UID of the app that performed the op on behalf of this app and
+         * as a result blamed the op on this app or {@link Process#INVALID_UID} if
+         * there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         *
+         * @return The proxy UID.
+         */
+        public int getProxyUid(@UidState int uidState, @OpFlags int flags) {
+            return (int) findFirstNonNegativeForFlagsInStates(mDurations,
+                    uidState, uidState, flags);
+        }
+
+        /**
+         * Gets the package name of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app or {@code null}
+         * if there is no proxy.
+         *
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyPackageName() {
+            return findFirstNonNullForFlagsInStates(mProxyPackageNames, MAX_PRIORITY_UID_STATE,
+                    MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
+        }
+
+        /**
+         * Gets the package name of the app that performed the op on behalf of this
+         * app and as a result blamed the op on this app for a UID state or
+         * {@code null} if there is no proxy.
+         *
+         * @param uidState The UID state for which to query. Could be one of
+         * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
+         * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
+         * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
+         * @return The proxy package name.
+         */
+        public @Nullable String getProxyPackageName(@UidState int uidState, @OpFlags int flags) {
+            return findFirstNonNullForFlagsInStates(mProxyPackageNames, uidState, uidState, flags);
         }
 
         @Override
@@ -2173,23 +2676,23 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
             dest.writeInt(mMode);
-            dest.writeLongArray(mTimes);
-            dest.writeLongArray(mRejectTimes);
-            dest.writeInt(mDuration);
             dest.writeBoolean(mRunning);
-            dest.writeInt(mProxyUid);
-            dest.writeString(mProxyPackageName);
+            writeLongSparseLongArrayToParcel(mAccessTimes, dest);
+            writeLongSparseLongArrayToParcel(mRejectTimes, dest);
+            writeLongSparseLongArrayToParcel(mDurations, dest);
+            writeLongSparseLongArrayToParcel(mProxyUids, dest);
+            writeLongSparseStringArrayToParcel(mProxyPackageNames, dest);
         }
 
         OpEntry(Parcel source) {
             mOp = source.readInt();
             mMode = source.readInt();
-            mTimes = source.createLongArray();
-            mRejectTimes = source.createLongArray();
-            mDuration = source.readInt();
             mRunning = source.readBoolean();
-            mProxyUid = source.readInt();
-            mProxyPackageName = source.readString();
+            mAccessTimes = readLongSparseLongArrayFromParcel(source);
+            mRejectTimes = readLongSparseLongArrayFromParcel(source);
+            mDurations = readLongSparseLongArrayFromParcel(source);
+            mProxyUids = readLongSparseLongArrayFromParcel(source);
+            mProxyPackageNames = readLongSparseStringArrayFromParcel(source);
         }
 
         public static final @android.annotation.NonNull Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
@@ -2226,14 +2729,17 @@
         private final @Nullable List<String> mOpNames;
         private final long mBeginTimeMillis;
         private final long mEndTimeMillis;
+        private final @OpFlags int mFlags;
 
         private HistoricalOpsRequest(int uid, @Nullable String packageName,
-                @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis) {
+                @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
+                @OpFlags int flags) {
             mUid = uid;
             mPackageName = packageName;
             mOpNames = opNames;
             mBeginTimeMillis = beginTimeMillis;
             mEndTimeMillis = endTimeMillis;
+            mFlags = flags;
         }
 
         /**
@@ -2249,6 +2755,7 @@
             private @Nullable List<String> mOpNames;
             private final long mBeginTimeMillis;
             private final long mEndTimeMillis;
+            private @OpFlags int mFlags = OP_FLAGS_ALL;
 
             /**
              * Creates a new builder.
@@ -2311,11 +2818,28 @@
             }
 
             /**
+             * Sets the op flags to query for. The flags specify the type of
+             * op data being queried.
+             *
+             * @param flags The flags which are any combination of
+             * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+             * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+             * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+             * for any flag.
+             * @return This builder.
+             */
+            public @NonNull Builder setFlags(@OpFlags int flags) {
+                Preconditions.checkFlagsArgument(flags, OP_FLAGS_ALL);
+                mFlags = flags;
+                return this;
+            }
+
+            /**
              * @return a new {@link HistoricalOpsRequest}.
              */
             public @NonNull HistoricalOpsRequest build() {
                 return new HistoricalOpsRequest(mUid, mPackageName, mOpNames,
-                        mBeginTimeMillis, mEndTimeMillis);
+                        mBeginTimeMillis, mEndTimeMillis, mFlags);
             }
         }
     }
@@ -2521,25 +3045,25 @@
         /** @hide */
         @TestApi
         public void increaseAccessCount(int opCode, int uid, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState,  @OpFlags int flags, long increment) {
             getOrCreateHistoricalUidOps(uid).increaseAccessCount(opCode,
-                    packageName, uidState, increment);
+                    packageName, uidState, flags, increment);
         }
 
         /** @hide */
         @TestApi
         public void increaseRejectCount(int opCode, int uid, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState, @OpFlags int flags, long increment) {
             getOrCreateHistoricalUidOps(uid).increaseRejectCount(opCode,
-                    packageName, uidState, increment);
+                    packageName, uidState, flags, increment);
         }
 
         /** @hide */
         @TestApi
         public void increaseAccessDuration(int opCode, int uid, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState, @OpFlags int flags, long increment) {
             getOrCreateHistoricalUidOps(uid).increaseAccessDuration(opCode,
-                    packageName, uidState, increment);
+                    packageName, uidState, flags, increment);
         }
 
         /** @hide */
@@ -2834,21 +3358,21 @@
         }
 
         private void increaseAccessCount(int opCode, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState, @OpFlags int flags, long increment) {
             getOrCreateHistoricalPackageOps(packageName).increaseAccessCount(
-                    opCode, uidState, increment);
+                    opCode, uidState, flags, increment);
         }
 
         private void increaseRejectCount(int opCode, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState,  @OpFlags int flags, long increment) {
             getOrCreateHistoricalPackageOps(packageName).increaseRejectCount(
-                    opCode, uidState, increment);
+                    opCode, uidState, flags, increment);
         }
 
         private void increaseAccessDuration(int opCode, @NonNull String packageName,
-                @UidState int uidState, long increment) {
+                @UidState int uidState, @OpFlags int flags, long increment) {
             getOrCreateHistoricalPackageOps(packageName).increaseAccessDuration(
-                    opCode, uidState, increment);
+                    opCode, uidState, flags, increment);
         }
 
         /**
@@ -3070,16 +3594,19 @@
             return true;
         }
 
-        private void increaseAccessCount(int opCode, @UidState int uidState, long increment) {
-            getOrCreateHistoricalOp(opCode).increaseAccessCount(uidState, increment);
+        private void increaseAccessCount(int opCode, @UidState int uidState,
+                @OpFlags int flags, long increment) {
+            getOrCreateHistoricalOp(opCode).increaseAccessCount(uidState, flags, increment);
         }
 
-        private void increaseRejectCount(int opCode, @UidState int uidState, long increment) {
-            getOrCreateHistoricalOp(opCode).increaseRejectCount(uidState, increment);
+        private void increaseRejectCount(int opCode, @UidState int uidState,
+                @OpFlags int flags, long increment) {
+            getOrCreateHistoricalOp(opCode).increaseRejectCount(uidState, flags, increment);
         }
 
-        private void increaseAccessDuration(int opCode, @UidState int uidState, long increment) {
-            getOrCreateHistoricalOp(opCode).increaseAccessDuration(uidState, increment);
+        private void increaseAccessDuration(int opCode, @UidState int uidState,
+                @OpFlags int flags, long increment) {
+            getOrCreateHistoricalOp(opCode).increaseAccessDuration(uidState, flags, increment);
         }
 
         /**
@@ -3095,7 +3622,6 @@
          * Gets number historical app ops.
          *
          * @return The number historical app ops.
-         *
          * @see #getOpAt(int)
          */
         public int getOpCount() {
@@ -3109,9 +3635,7 @@
          * Gets the historical op at a given index.
          *
          * @param index The index to lookup.
-         *
          * @return The op at the given index.
-         *
          * @see #getOpCount()
          */
         public @NonNull HistoricalOp getOpAt(int index) {
@@ -3125,7 +3649,6 @@
          * Gets the historical entry for a given op name.
          *
          * @param opName The op name.
-         *
          * @return The historical entry for that op name.
          */
         public @Nullable HistoricalOp getOp(@NonNull String opName) {
@@ -3219,39 +3742,33 @@
     @SystemApi
     public static final class HistoricalOp implements Parcelable {
         private final int mOp;
-        private @Nullable long[] mAccessCount;
-        private @Nullable long[] mRejectCount;
-        private @Nullable long[] mAccessDuration;
+        private @Nullable LongSparseLongArray mAccessCount;
+        private @Nullable LongSparseLongArray mRejectCount;
+        private @Nullable LongSparseLongArray mAccessDuration;
 
         /** @hide */
         public HistoricalOp(int op) {
             mOp = op;
-            mAccessCount = new long[_NUM_UID_STATE];
-            mRejectCount = new long[_NUM_UID_STATE];
-            mAccessDuration = new long[_NUM_UID_STATE];
         }
 
         private HistoricalOp(@NonNull HistoricalOp other) {
             mOp = other.mOp;
             if (other.mAccessCount != null) {
-                System.arraycopy(other.mAccessCount, 0, getOrCreateAccessCount(),
-                        0, other.mAccessCount.length);
+                mAccessCount = other.mAccessCount.clone();
             }
             if (other.mRejectCount != null) {
-                System.arraycopy(other.mRejectCount, 0, getOrCreateRejectCount(),
-                        0, other.mRejectCount.length);
+                mRejectCount = other.mRejectCount.clone();
             }
             if (other.mAccessDuration != null) {
-                System.arraycopy(other.mAccessDuration, 0, getOrCreateAccessDuration(),
-                        0, other.mAccessDuration.length);
+                mAccessDuration = other.mAccessDuration.clone();
             }
         }
 
         private HistoricalOp(@NonNull Parcel parcel) {
             mOp = parcel.readInt();
-            mAccessCount = parcel.createLongArray();
-            mRejectCount = parcel.createLongArray();
-            mAccessDuration = parcel.createLongArray();
+            mAccessCount = readLongSparseLongArrayFromParcel(parcel);
+            mRejectCount = readLongSparseLongArrayFromParcel(parcel);
+            mAccessDuration = readLongSparseLongArrayFromParcel(parcel);
         }
 
         private void filter(double scaleFactor) {
@@ -3266,90 +3783,64 @@
                     && !hasData(mAccessDuration);
         }
 
-        private boolean hasData(@NonNull long[] array) {
-            for (long value : array) {
-                if (value != 0) {
-                    return true;
-                }
-            }
-            return false;
+        private boolean hasData(@NonNull LongSparseLongArray array) {
+            return (array != null && array.size() > 0);
         }
 
         private @Nullable HistoricalOp splice(double fractionToRemove) {
-            HistoricalOp splice = null;
-            if (mAccessCount != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    final long spliceAccessCount = Math.round(
-                            mAccessCount[i] * fractionToRemove);
-                    if (spliceAccessCount > 0) {
-                        if (splice == null) {
-                            splice = new HistoricalOp(mOp);
-                        }
-                        splice.getOrCreateAccessCount()[i] = spliceAccessCount;
-                        mAccessCount[i] -= spliceAccessCount;
-                    }
-                }
-            }
-
-            if (mRejectCount != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    final long spliceRejectCount = Math.round(
-                            mRejectCount[i] * fractionToRemove);
-
-                    if (spliceRejectCount > 0) {
-                        if (splice == null) {
-                            splice = new HistoricalOp(mOp);
-                        }
-                        splice.getOrCreateRejectCount()[i] = spliceRejectCount;
-                        mRejectCount[i] -= spliceRejectCount;
-                    }
-                }
-            }
-
-            if (mAccessDuration != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    final long spliceAccessDuration =  Math.round(
-                            mAccessDuration[i] * fractionToRemove);
-                    if (spliceAccessDuration > 0) {
-                        if (splice == null) {
-                            splice = new HistoricalOp(mOp);
-                        }
-                        splice.getOrCreateAccessDuration()[i] = spliceAccessDuration;
-                        mAccessDuration[i] -= spliceAccessDuration;
-                    }
-                }
-            }
+            final HistoricalOp splice = new HistoricalOp(mOp);
+            splice(mAccessCount, splice::getOrCreateAccessCount, fractionToRemove);
+            splice(mRejectCount, splice::getOrCreateRejectCount, fractionToRemove);
+            splice(mAccessDuration, splice::getOrCreateAccessDuration, fractionToRemove);
             return splice;
         }
 
+        private static void splice(@Nullable LongSparseLongArray sourceContainer,
+                @NonNull Supplier<LongSparseLongArray> destContainerProvider,
+                    double fractionToRemove) {
+            if (sourceContainer != null) {
+                final int size = sourceContainer.size();
+                for (int i = 0; i < size; i++) {
+                    final long key = sourceContainer.keyAt(i);
+                    final long value = sourceContainer.valueAt(i);
+                    final long removedFraction = Math.round(value * fractionToRemove);
+                    if (removedFraction > 0) {
+                        destContainerProvider.get().put(key, removedFraction);
+                        sourceContainer.put(key, value - removedFraction);
+                    }
+                }
+            }
+        }
+
         private void merge(@NonNull HistoricalOp other) {
-            if (other.mAccessCount != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    getOrCreateAccessCount()[i] += other.mAccessCount[i];
-                }
-            }
-            if (other.mRejectCount != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    getOrCreateRejectCount()[i] += other.mRejectCount[i];
-                }
-            }
-            if (other.mAccessDuration != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    getOrCreateAccessDuration()[i] += other.mAccessDuration[i];
-                }
-            }
+            merge(this::getOrCreateAccessCount, other.mAccessCount);
+            merge(this::getOrCreateRejectCount, other.mRejectCount);
+            merge(this::getOrCreateAccessDuration, other.mAccessDuration);
         }
 
-        private void increaseAccessCount(@UidState int uidState, long increment) {
-            getOrCreateAccessCount()[uidState] += increment;
+        private void increaseAccessCount(@UidState int uidState, @OpFlags int flags,
+                long increment) {
+            increaseCount(getOrCreateAccessCount(), uidState, flags, increment);
         }
 
-        private void increaseRejectCount(@UidState int uidState, long increment) {
-            getOrCreateRejectCount()[uidState] += increment;
+        private void increaseRejectCount(@UidState int uidState, @OpFlags int flags,
+                long increment) {
+            increaseCount(getOrCreateRejectCount(), uidState, flags, increment);
         }
 
-        private void increaseAccessDuration(@UidState int uidState, long increment) {
-            getOrCreateAccessDuration()[uidState] += increment;
+        private void increaseAccessDuration(@UidState int uidState, @OpFlags int flags,
+                long increment) {
+            increaseCount(getOrCreateAccessDuration(), uidState, flags, increment);
+        }
+
+        private void increaseCount(@NonNull LongSparseLongArray counts,
+                @UidState int uidState, @OpFlags int flags, long increment) {
+            while (flags != 0) {
+                final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+                flags &= ~flag;
+                final long key = makeKey(uidState, flag);
+                counts.put(key, counts.get(key) + increment);
+            }
         }
 
         /**
@@ -3369,154 +3860,186 @@
         /**
          * Gets the number times the op was accessed (performed) in the foreground.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The times the op was accessed in the foreground.
          *
-         * @see #getBackgroundAccessCount()
-         * @see #getAccessCount(int)
+         * @see #getBackgroundAccessCount(int)
+         * @see #getAccessCount(int, int, int)
          */
-        public long getForegroundAccessCount() {
-            if (mAccessCount == null) {
-                return 0;
-            }
-            return sum(mAccessCount, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1);
+        public long getForegroundAccessCount(@OpFlags int flags) {
+            return sumForFlagsInStates(mAccessCount, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
         }
 
         /**
          * Gets the number times the op was accessed (performed) in the background.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The times the op was accessed in the background.
          *
-         * @see #getForegroundAccessCount()
-         * @see #getAccessCount(int)
+         * @see #getForegroundAccessCount(int)
+         * @see #getAccessCount(int, int, int)
          */
-        public long getBackgroundAccessCount() {
-            if (mAccessCount == null) {
-                return 0;
-            }
-            return sum(mAccessCount, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE);
+        public long getBackgroundAccessCount(@OpFlags int flags) {
+            return sumForFlagsInStates(mAccessCount, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * Gets the number times the op was accessed (performed) for a given uid state.
+         * Gets the number times the op was accessed (performed) for a
+         * range of uid states.
          *
-         * @param uidState The UID state for which to query. Could be one of
+         * @param fromUidState The UID state from which to query. Could be one of
          * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
          * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
          * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
          * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state to which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          *
          * @return The times the op was accessed for the given UID state.
          *
-         * @see #getForegroundAccessCount()
-         * @see #getBackgroundAccessCount()
+         * @see #getForegroundAccessCount(int)
+         * @see #getBackgroundAccessCount(int)
          */
-        public long getAccessCount(@UidState int uidState) {
-            if (mAccessCount == null) {
-                return 0;
-            }
-            return mAccessCount[uidState];
+        public long getAccessCount(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return sumForFlagsInStates(mAccessCount, fromUidState, toUidState, flags);
         }
 
         /**
          * Gets the number times the op was rejected in the foreground.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The times the op was rejected in the foreground.
          *
-         * @see #getBackgroundRejectCount()
-         * @see #getRejectCount(int)
+         * @see #getBackgroundRejectCount(int)
+         * @see #getRejectCount(int, int, int)
          */
-        public long getForegroundRejectCount() {
-            if (mRejectCount == null) {
-                return 0;
-            }
-            return sum(mRejectCount, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1);
+        public long getForegroundRejectCount(@OpFlags int flags) {
+            return sumForFlagsInStates(mRejectCount, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
         }
 
         /**
          * Gets the number times the op was rejected in the background.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The times the op was rejected in the background.
          *
-         * @see #getForegroundRejectCount()
-         * @see #getRejectCount(int)
+         * @see #getForegroundRejectCount(int)
+         * @see #getRejectCount(int, int, int)
          */
-        public long getBackgroundRejectCount() {
-            if (mRejectCount == null) {
-                return 0;
-            }
-            return sum(mRejectCount, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE);
+        public long getBackgroundRejectCount(@OpFlags int flags) {
+            return sumForFlagsInStates(mRejectCount, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * Gets the number times the op was rejected for a given uid state.
+         * Gets the number times the op was rejected for a given range of UID states.
          *
-         * @param uidState The UID state for which to query. Could be one of
+         * @param fromUidState The UID state from which to query. Could be one of
          * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
          * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
          * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
          * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state to which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          *
          * @return The times the op was rejected for the given UID state.
          *
-         * @see #getForegroundRejectCount()
-         * @see #getBackgroundRejectCount()
+         * @see #getForegroundRejectCount(int)
+         * @see #getBackgroundRejectCount(int)
          */
-        public long getRejectCount(@UidState int uidState) {
-            if (mRejectCount == null) {
-                return 0;
-            }
-            return mRejectCount[uidState];
+        public long getRejectCount(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return sumForFlagsInStates(mRejectCount, fromUidState, toUidState, flags);
         }
 
         /**
          * Gets the total duration the app op was accessed (performed) in the foreground.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The total duration the app op was accessed in the foreground.
          *
-         * @see #getBackgroundAccessDuration()
-         * @see #getAccessDuration(int)
+         * @see #getBackgroundAccessDuration(int)
+         * @see #getAccessDuration(int, int, int)
          */
-        public long getForegroundAccessDuration() {
-            if (mAccessDuration == null) {
-                return 0;
-            }
-            return sum(mAccessDuration, UID_STATE_PERSISTENT, UID_STATE_LAST_NON_RESTRICTED + 1);
+        public long getForegroundAccessDuration(@OpFlags int flags) {
+            return sumForFlagsInStates(mAccessDuration, MAX_PRIORITY_UID_STATE,
+                    resolveFirstUnrestrictedUidState(mOp), flags);
         }
 
         /**
          * Gets the total duration the app op was accessed (performed) in the background.
          *
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          * @return The total duration the app op was accessed in the background.
          *
-         * @see #getForegroundAccessDuration()
-         * @see #getAccessDuration(int)
+         * @see #getForegroundAccessDuration(int)
+         * @see #getAccessDuration(int, int, int)
          */
-        public long getBackgroundAccessDuration() {
-            if (mAccessDuration == null) {
-                return 0;
-            }
-            return sum(mAccessDuration, UID_STATE_LAST_NON_RESTRICTED + 1, _NUM_UID_STATE);
+        public long getBackgroundAccessDuration(@OpFlags int flags) {
+            return sumForFlagsInStates(mAccessDuration, resolveLastRestrictedUidState(mOp),
+                    MIN_PRIORITY_UID_STATE, flags);
         }
 
         /**
-         * Gets the total duration the app op was accessed (performed) for a given UID state.
+         * Gets the total duration the app op was accessed (performed) for a given
+         * range of UID states.
          *
-         * @param uidState The UID state for which to query. Could be one of
+         * @param fromUidState The UID state from which to query. Could be one of
          * {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
          * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
          * {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
          * {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
+         * @param toUidState The UID state from which to query.
+         * @param flags The flags which are any combination of
+         * {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
+         * {@link #OP_FLAG_UNTRUSTED_PROXY}, {@link #OP_FLAG_TRUSTED_PROXIED},
+         * {@link #OP_FLAG_UNTRUSTED_PROXIED}. You can use {@link #OP_FLAGS_ALL}
+         * for any flag.
          *
          * @return The total duration the app op was accessed for the given UID state.
          *
-         * @see #getForegroundAccessDuration()
-         * @see #getBackgroundAccessDuration()
+         * @see #getForegroundAccessDuration(int)
+         * @see #getBackgroundAccessDuration(int)
          */
-        public long getAccessDuration(@UidState int uidState) {
-            if (mAccessDuration == null) {
-                return 0;
-            }
-            return mAccessDuration[uidState];
+        public long getAccessDuration(@UidState int fromUidState, @UidState int toUidState,
+                @OpFlags int flags) {
+            return sumForFlagsInStates(mAccessDuration, fromUidState, toUidState, flags);
         }
 
         @Override
@@ -3527,80 +4050,11 @@
         @Override
         public void writeToParcel(Parcel parcel, int flags) {
             parcel.writeInt(mOp);
-            parcel.writeLongArray(mAccessCount);
-            parcel.writeLongArray(mRejectCount);
-            parcel.writeLongArray(mAccessDuration);
+            writeLongSparseLongArrayToParcel(mAccessCount, parcel);
+            writeLongSparseLongArrayToParcel(mRejectCount, parcel);
+            writeLongSparseLongArrayToParcel(mAccessDuration, parcel);
         }
 
-        private void accept(@NonNull HistoricalOpsVisitor visitor) {
-            visitor.visitHistoricalOp(this);
-        }
-
-        private @NonNull long[] getOrCreateAccessCount() {
-            if (mAccessCount == null) {
-                mAccessCount = new long[_NUM_UID_STATE];
-            }
-            return mAccessCount;
-        }
-
-        private @NonNull long[] getOrCreateRejectCount() {
-            if (mRejectCount == null) {
-                mRejectCount = new long[_NUM_UID_STATE];
-            }
-            return mRejectCount;
-        }
-
-        private @NonNull long[] getOrCreateAccessDuration() {
-            if (mAccessDuration == null) {
-                mAccessDuration = new long[_NUM_UID_STATE];
-            }
-            return mAccessDuration;
-        }
-
-        /**
-         *
-         * Computes the sum given the start and end index.
-         *
-         * @param counts The data array.
-         * @param start The start index (inclusive)
-         * @param end The end index (exclusive)
-         * @return The sum.
-         */
-        private static long sum(@NonNull long[] counts, int start, int end) {
-            long totalCount = 0;
-            for (int i = start; i < end; i++) {
-                totalCount += counts[i];
-            }
-            return totalCount;
-        }
-
-        /**
-         * Multiplies the entries in the array with the passed in scale factor and
-         * rounds the result at up 0.5 boundary.
-         *
-         * @param data The data to scale.
-         * @param scaleFactor The scale factor.
-         */
-        private static void scale(@NonNull long[] data, double scaleFactor) {
-            if (data != null) {
-                for (int i = 0; i < _NUM_UID_STATE; i++) {
-                    data[i] = (long) HistoricalOps.round((double) data[i] * scaleFactor);
-                }
-            }
-        }
-
-        public static final @android.annotation.NonNull Creator<HistoricalOp> CREATOR = new Creator<HistoricalOp>() {
-            @Override
-            public @NonNull HistoricalOp createFromParcel(@NonNull Parcel source) {
-                return new HistoricalOp(source);
-            }
-
-            @Override
-            public @NonNull HistoricalOp[] newArray(int size) {
-                return new HistoricalOp[size];
-            }
-        };
-
         @Override
         public boolean equals(Object obj) {
             if (this == obj) {
@@ -3613,23 +4067,201 @@
             if (mOp != other.mOp) {
                 return false;
             }
-            if (!Arrays.equals(mAccessCount, other.mAccessCount)) {
+            if (!Objects.equals(mAccessCount, other.mAccessCount)) {
                 return false;
             }
-            if (!Arrays.equals(mRejectCount, other.mRejectCount)) {
+            if (!Objects.equals(mRejectCount, other.mRejectCount)) {
                 return false;
             }
-            return Arrays.equals(mAccessDuration, other.mAccessDuration);
+            return Objects.equals(mAccessDuration, other.mAccessDuration);
         }
 
         @Override
         public int hashCode() {
             int result = mOp;
-            result = 31 * result + Arrays.hashCode(mAccessCount);
-            result = 31 * result + Arrays.hashCode(mRejectCount);
-            result = 31 * result + Arrays.hashCode(mAccessDuration);
+            result = 31 * result + Objects.hashCode(mAccessCount);
+            result = 31 * result + Objects.hashCode(mRejectCount);
+            result = 31 * result + Objects.hashCode(mAccessDuration);
             return result;
         }
+
+        private void accept(@NonNull HistoricalOpsVisitor visitor) {
+            visitor.visitHistoricalOp(this);
+        }
+
+        private @NonNull LongSparseLongArray getOrCreateAccessCount() {
+            if (mAccessCount == null) {
+                mAccessCount = new LongSparseLongArray();
+            }
+            return mAccessCount;
+        }
+
+        private @NonNull LongSparseLongArray getOrCreateRejectCount() {
+            if (mRejectCount == null) {
+                mRejectCount = new LongSparseLongArray();
+            }
+            return mRejectCount;
+        }
+
+        private @NonNull LongSparseLongArray getOrCreateAccessDuration() {
+            if (mAccessDuration == null) {
+                mAccessDuration = new LongSparseLongArray();
+            }
+            return mAccessDuration;
+        }
+
+        /**
+         * Multiplies the entries in the array with the passed in scale factor and
+         * rounds the result at up 0.5 boundary.
+         *
+         * @param data The data to scale.
+         * @param scaleFactor The scale factor.
+         */
+        private static void scale(@NonNull LongSparseLongArray data, double scaleFactor) {
+            if (data != null) {
+                final int size = data.size();
+                for (int i = 0; i < size; i++) {
+                    data.put(data.keyAt(i), (long) HistoricalOps.round(
+                            (double) data.valueAt(i) * scaleFactor));
+                }
+            }
+        }
+
+        /**
+         * Merges two arrays while lazily acquiring the destination.
+         *
+         * @param thisSupplier The destination supplier.
+         * @param other The array to merge in.
+         */
+        private static void merge(@NonNull Supplier<LongSparseLongArray> thisSupplier,
+                @Nullable LongSparseLongArray other) {
+            if (other != null) {
+                final int otherSize = other.size();
+                for (int i = 0; i < otherSize; i++) {
+                    final LongSparseLongArray that = thisSupplier.get();
+                    final long otherKey = other.keyAt(i);
+                    final long otherValue = other.valueAt(i);
+                    that.put(otherKey, that.get(otherKey) + otherValue);
+                }
+            }
+        }
+
+        /** @hide */
+        public @Nullable LongSparseArray<Object> collectKeys() {
+            LongSparseArray<Object> result = AppOpsManager.collectKeys(mAccessCount,
+                null /*result*/);
+            result = AppOpsManager.collectKeys(mRejectCount, result);
+            result = AppOpsManager.collectKeys(mAccessDuration, result);
+            return result;
+        }
+
+        public static final @android.annotation.NonNull Creator<HistoricalOp> CREATOR =
+                new Creator<HistoricalOp>() {
+            @Override
+            public @NonNull HistoricalOp createFromParcel(@NonNull Parcel source) {
+                return new HistoricalOp(source);
+            }
+
+            @Override
+            public @NonNull HistoricalOp[] newArray(int size) {
+                return new HistoricalOp[size];
+            }
+        };
+    }
+
+    /**
+     * Computes the sum of the counts for the given flags in between the begin and
+     * end UID states.
+     *
+     * @param counts The data array.
+     * @param beginUidState The beginning UID state (exclusive).
+     * @param endUidState The end UID state.
+     * @param flags The UID flags.
+     * @return The sum.
+     */
+    private static long sumForFlagsInStates(@Nullable LongSparseLongArray counts,
+            @UidState int beginUidState, @UidState int endUidState, @OpFlags int flags) {
+        if (counts == null) {
+            return 0;
+        }
+        long sum = 0;
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            for (int uidState : UID_STATES) {
+                if (uidState < beginUidState || uidState > endUidState) {
+                    continue;
+                }
+                final long key = makeKey(uidState, flag);
+                sum += counts.get(key);
+            }
+        }
+        return sum;
+    }
+
+    /**
+     * Finds the first non-negative value for the given flags in between the begin and
+     * end UID states.
+     *
+     * @param counts The data array.
+     * @param flags The UID flags.
+     * @param beginUidState The beginning UID state (exclusive).
+     * @param endUidState The end UID state.
+     * @return The non-negative value or -1.
+     */
+    private static long findFirstNonNegativeForFlagsInStates(@Nullable LongSparseLongArray counts,
+            @OpFlags int flags, @UidState int beginUidState, @UidState int endUidState) {
+        if (counts == null) {
+            return -1;
+        }
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            for (int uidState : UID_STATES) {
+                if (uidState < beginUidState || uidState > endUidState) {
+                    continue;
+                }
+                final long key = makeKey(uidState, flag);
+                final long value = counts.get(key);
+                if (value >= 0) {
+                    return value;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Finds the first non-null value for the given flags in between the begin and
+     * end UID states.
+     *
+     * @param counts The data array.
+     * @param flags The UID flags.
+     * @param beginUidState The beginning UID state (exclusive).
+     * @param endUidState The end UID state.
+     * @return The non-negative value or -1.
+     */
+    private static @Nullable String findFirstNonNullForFlagsInStates(
+            @Nullable LongSparseArray<String> counts, @OpFlags int flags,
+            @UidState int beginUidState, @UidState int endUidState) {
+        if (counts == null) {
+            return null;
+        }
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            for (int uidState : UID_STATES) {
+                if (uidState < beginUidState || uidState > endUidState) {
+                    continue;
+                }
+                final long key = makeKey(uidState, flag);
+                final String value = counts.get(key);
+                if (value != null) {
+                    return value;
+                }
+            }
+        }
+        return null;
     }
 
     /**
@@ -3800,7 +4432,7 @@
         Preconditions.checkNotNull(callback, "callback cannot be null");
         try {
             mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
-                    request.mBeginTimeMillis, request.mEndTimeMillis,
+                    request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
                     new RemoteCallback((result) -> {
                 final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
                 final long identity = Binder.clearCallingIdentity();
@@ -3840,7 +4472,7 @@
         try {
             mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
                     request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
-                    new RemoteCallback((result) -> {
+                    request.mFlags, new RemoteCallback((result) -> {
                 final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
                 final long identity = Binder.clearCallingIdentity();
                 try {
@@ -4310,7 +4942,20 @@
      * Like {@link #checkOp} but returns the <em>raw</em> mode associated with the op.
      * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
      */
-    public int unsafeCheckOpRaw(String op, int uid, String packageName) {
+    public int unsafeCheckOpRaw(@NonNull String op, int uid, String packageName) {
+        try {
+            return mService.checkOperationRaw(strOpToOp(op), uid, packageName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Like {@link #unsafeCheckOpNoThrow(String, int, String)} but returns the <em>raw</em>
+     * mode associated with the op. Does not throw a security exception, does not translate
+     * {@link #MODE_FOREGROUND}.
+     */
+    public int unsafeCheckOpRawNoThrow(@NonNull String op, int uid, @NonNull String packageName) {
         try {
             return mService.checkOperationRaw(strOpToOp(op), uid, packageName);
         } catch (RemoteException e) {
@@ -4899,16 +5544,110 @@
     }
 
     /**
-     * @hide
+     * Computes the max for the given flags in between the begin and
+     * end UID states.
+     *
+     * @param counts The data array.
+     * @param flags The UID flags.
+     * @param beginUidState The beginning UID state (exclusive).
+     * @param endUidState The end UID state.
+     * @return The sum.
      */
-    public static long maxTime(long[] times, int start, int end) {
-        long time = 0;
-        for (int i = start; i < end; i++) {
-            if (times[i] > time) {
-                time = times[i];
+    private static long maxForFlagsInStates(@Nullable LongSparseLongArray counts,
+            @UidState int beginUidState, @UidState int endUidState,
+            @OpFlags int flags) {
+        if (counts == null) {
+            return 0;
+        }
+        long max = 0;
+        while (flags != 0) {
+            final int flag = 1 << Integer.numberOfTrailingZeros(flags);
+            flags &= ~flag;
+            for (int uidState : UID_STATES) {
+                if (uidState < beginUidState || uidState > endUidState) {
+                    continue;
+                }
+                final long key = makeKey(uidState, flag);
+                max = Math.max(max, counts.get(key));
             }
         }
-        return time;
+        return max;
+    }
+
+
+    private static void writeLongSparseLongArrayToParcel(
+            @Nullable LongSparseLongArray array, @NonNull Parcel parcel) {
+        if (array != null) {
+            final int size = array.size();
+            parcel.writeInt(size);
+            for (int i = 0; i < size; i++) {
+                parcel.writeLong(array.keyAt(i));
+                parcel.writeLong(array.valueAt(i));
+            }
+        } else {
+            parcel.writeInt(-1);
+        }
+    }
+
+    private static @Nullable LongSparseLongArray readLongSparseLongArrayFromParcel(
+            @NonNull Parcel parcel) {
+        final int size = parcel.readInt();
+        if (size < 0) {
+            return null;
+        }
+        final LongSparseLongArray array = new LongSparseLongArray(size);
+        for (int i = 0; i < size; i++) {
+            array.append(parcel.readLong(), parcel.readLong());
+        }
+        return array;
+    }
+
+    private static void writeLongSparseStringArrayToParcel(
+            @Nullable LongSparseArray<String> array, @NonNull Parcel parcel) {
+        if (array != null) {
+            final int size = array.size();
+            parcel.writeInt(size);
+            for (int i = 0; i < size; i++) {
+                parcel.writeLong(array.keyAt(i));
+                parcel.writeString(array.valueAt(i));
+            }
+        } else {
+            parcel.writeInt(-1);
+        }
+    }
+
+    private static @Nullable LongSparseArray<String> readLongSparseStringArrayFromParcel(
+            @NonNull Parcel parcel) {
+        final int size = parcel.readInt();
+        if (size < 0) {
+            return null;
+        }
+        final LongSparseArray<String> array = new LongSparseArray<>(size);
+        for (int i = 0; i < size; i++) {
+            array.append(parcel.readLong(), parcel.readString());
+        }
+        return array;
+    }
+
+    /**
+     * Collects the keys from an array to the result creating the result if needed.
+     *
+     * @param array The array whose keys to collect.
+     * @param result The optional result store collected keys.
+     * @return The result collected keys array.
+     */
+    private static LongSparseArray<Object> collectKeys(@Nullable LongSparseLongArray array,
+            @Nullable LongSparseArray<Object> result) {
+        if (array != null) {
+            if (result == null) {
+                result = new LongSparseArray<>();
+            }
+            final int accessSize = array.size();
+            for (int i = 0; i < accessSize; i++) {
+                result.put(array.keyAt(i), null);
+            }
+        }
+        return result;
     }
 
     /** @hide */
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 4a826d1..010a900 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -16,18 +16,15 @@
 
 package android.app;
 
-import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.NotificationManager.InterruptionFilter;
 import android.content.ComponentName;
-import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.service.notification.ZenPolicy;
 import android.service.notification.Condition;
-
-import com.android.internal.util.Preconditions;
+import android.service.notification.ZenPolicy;
 
 import java.util.Objects;
 
@@ -92,8 +89,9 @@
      *               action ({@link Condition#STATE_TRUE}).
      * @param enabled Whether the rule is enabled.
      */
-    public AutomaticZenRule(String name, ComponentName owner, ComponentName configurationActivity,
-            Uri conditionId, ZenPolicy policy, int interruptionFilter, boolean enabled) {
+    public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
+            @Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
+            @Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
         this.name = name;
         this.owner = owner;
         this.configurationActivity = configurationActivity;
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 062a462..161e2ad 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -61,7 +61,7 @@
             "android:broadcast.dontSendToRestrictedApps";
 
     /**
-     * Corresponds to {@link #setAllowBackgroundActivityStarts}.
+     * Corresponds to {@link #setBackgroundActivityStartsAllowed}.
      */
     static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
             "android:broadcast.allowBackgroundActivityStarts";
@@ -161,7 +161,7 @@
      * the broadcast dispatch. Default value is {@code false}
      */
     @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND)
-    public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) {
+    public void setBackgroundActivityStartsAllowed(boolean allowBackgroundActivityStarts) {
         mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
     }
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b607f9a..daf2366 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -102,6 +102,7 @@
 import java.util.concurrent.Executor;
 
 class ReceiverRestrictedContext extends ContextWrapper {
+    @UnsupportedAppUsage
     ReceiverRestrictedContext(Context base) {
         super(base);
     }
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index e20c490..7ae88fd 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1158,6 +1158,7 @@
      * @param ids the IDs of the downloads
      * @hide
      */
+    @UnsupportedAppUsage
     public void restartDownload(long... ids) {
         Cursor cursor = query(new Query().setFilterById(ids));
         try {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 5cbb599..16fe7db 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -102,15 +102,21 @@
     // Special low-level communication with activity manager.
     void handleApplicationCrash(in IBinder app,
             in ApplicationErrorReport.ParcelableCrashInfo crashInfo);
+    @UnsupportedAppUsage
     int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
             in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
             int flags, in ProfilerInfo profilerInfo, in Bundle options);
+    @UnsupportedAppUsage
     void unhandledBack();
+    @UnsupportedAppUsage
     boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask);
+    @UnsupportedAppUsage
     Intent registerReceiver(in IApplicationThread caller, in String callerPackage,
             in IIntentReceiver receiver, in IntentFilter filter,
             in String requiredPermission, int userId, int flags);
+    @UnsupportedAppUsage
     void unregisterReceiver(in IIntentReceiver receiver);
+    @UnsupportedAppUsage
     int broadcastIntent(in IApplicationThread caller, in Intent intent,
             in String resolvedType, in IIntentReceiver resultTo, int resultCode,
             in String resultData, in Bundle map, in String[] requiredPermissions,
@@ -120,21 +126,27 @@
             boolean abortBroadcast, int flags);
     void attachApplication(in IApplicationThread app, long startSeq);
     List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);
+    @UnsupportedAppUsage
     List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType,
             int ignoreWindowingMode);
+    @UnsupportedAppUsage
     void moveTaskToFront(int task, int flags, in Bundle options);
+    @UnsupportedAppUsage
     int getTaskForActivity(in IBinder token, in boolean onlyRoot);
     ContentProviderHolder getContentProvider(in IApplicationThread caller, in String callingPackage,
             in String name, int userId, boolean stable);
+    @UnsupportedAppUsage
     void publishContentProviders(in IApplicationThread caller,
             in List<ContentProviderHolder> providers);
     boolean refContentProvider(in IBinder connection, int stableDelta, int unstableDelta);
     PendingIntent getRunningServiceControlPanel(in ComponentName service);
     ComponentName startService(in IApplicationThread caller, in Intent service,
             in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
+    @UnsupportedAppUsage
     int stopService(in IApplicationThread caller, in Intent service,
             in String resolvedType, int userId);
     // Currently keeping old bindService because it is on the greylist
+    @UnsupportedAppUsage
     int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
             in String resolvedType, in IServiceConnection connection, int flags,
             in String callingPackage, int userId);
@@ -142,11 +154,15 @@
             in String resolvedType, in IServiceConnection connection, int flags,
             in String instanceName, in String callingPackage, int userId);
     void updateServiceGroup(in IServiceConnection connection, int group, int importance);
+    @UnsupportedAppUsage
     boolean unbindService(in IServiceConnection connection);
     void publishService(in IBinder token, in Intent intent, in IBinder service);
+    @UnsupportedAppUsage
     void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
     void setAgentApp(in String packageName, @nullable String agent);
+    @UnsupportedAppUsage
     void setAlwaysFinish(boolean enabled);
+    @UnsupportedAppUsage
     boolean startInstrumentation(in ComponentName className, in String profileFile,
             int flags, in Bundle arguments, in IInstrumentationWatcher watcher,
             in IUiAutomationConnection connection, int userId,
@@ -159,6 +175,7 @@
      *         system. Corresponds to the configuration of the default display.
      * @throws RemoteException
      */
+    @UnsupportedAppUsage
     Configuration getConfiguration();
     /**
      * Updates global configuration and applies changes to the entire system.
@@ -167,10 +184,14 @@
      * @throws RemoteException
      * @return Returns true if the configuration was updated.
      */
+    @UnsupportedAppUsage
     boolean updateConfiguration(in Configuration values);
     boolean stopServiceToken(in ComponentName className, in IBinder token, int startId);
+    @UnsupportedAppUsage
     void setProcessLimit(int max);
+    @UnsupportedAppUsage
     int getProcessLimit();
+    @UnsupportedAppUsage
     int checkPermission(in String permission, int pid, int uid);
     int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId,
             in IBinder callerToken);
@@ -178,6 +199,7 @@
             int mode, int userId);
     void revokeUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
             int mode, int userId);
+    @UnsupportedAppUsage
     void setActivityController(in IActivityController watcher, boolean imAMonkey);
     void showWaitingForDebugger(in IApplicationThread who, boolean waiting);
     /*
@@ -186,8 +208,10 @@
      */
     void signalPersistentProcesses(int signal);
 
+    @UnsupportedAppUsage
     ParceledListSlice getRecentTasks(int maxNum, int flags, int userId);
     oneway void serviceDoneExecuting(in IBinder token, int type, int startId, int res);
+    @UnsupportedAppUsage
     IIntentSender getIntentSender(int type, in String packageName, in IBinder token,
             in String resultWho, int requestCode, in Intent[] intents, in String[] resolvedTypes,
             int flags, in Bundle options, int userId);
@@ -199,28 +223,39 @@
     void noteWakeupAlarm(in IIntentSender sender, in WorkSource workSource, int sourceUid,
             in String sourcePkg, in String tag);
     void removeContentProvider(in IBinder connection, boolean stable);
+    @UnsupportedAppUsage
     void setRequestedOrientation(in IBinder token, int requestedOrientation);
     void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
+    @UnsupportedAppUsage
     void setProcessImportant(in IBinder token, int pid, boolean isForeground, String reason);
     void setServiceForeground(in ComponentName className, in IBinder token,
             int id, in Notification notification, int flags, int foregroundServiceType);
     int getForegroundServiceType(in ComponentName className, in IBinder token);
+    @UnsupportedAppUsage
     boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
+    @UnsupportedAppUsage
     void getMemoryInfo(out ActivityManager.MemoryInfo outInfo);
     List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
     boolean clearApplicationUserData(in String packageName, boolean keepState,
             in IPackageDataObserver observer, int userId);
+    @UnsupportedAppUsage
     void forceStopPackage(in String packageName, int userId);
     boolean killPids(in int[] pids, in String reason, boolean secure);
+    @UnsupportedAppUsage
     List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags);
     // Retrieve running application processes in the system
+    @UnsupportedAppUsage
     List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
     IBinder peekService(in Intent service, in String resolvedType, in String callingPackage);
     // Turn on/off profiling in a particular process.
+    @UnsupportedAppUsage
     boolean profileControl(in String process, int userId, boolean start,
             in ProfilerInfo profilerInfo, int profileType);
+    @UnsupportedAppUsage
     boolean shutdown(int timeout);
+    @UnsupportedAppUsage
     void stopAppSwitches();
+    @UnsupportedAppUsage
     void resumeAppSwitches();
     boolean bindBackupAgent(in String packageName, int backupRestoreMode, int targetUserId);
     void backupAgentCreated(in String packageName, in IBinder agent, int userId);
@@ -230,60 +265,83 @@
             boolean requireFull, in String name, in String callerPackage);
     void addPackageDependency(in String packageName);
     void killApplication(in String pkg, int appId, int userId, in String reason);
+    @UnsupportedAppUsage
     void closeSystemDialogs(in String reason);
+    @UnsupportedAppUsage
     Debug.MemoryInfo[] getProcessMemoryInfo(in int[] pids);
     void killApplicationProcess(in String processName, int uid);
     // Special low-level communication with activity manager.
     boolean handleApplicationWtf(in IBinder app, in String tag, boolean system,
             in ApplicationErrorReport.ParcelableCrashInfo crashInfo);
+    @UnsupportedAppUsage
     void killBackgroundProcesses(in String packageName, int userId);
     boolean isUserAMonkey();
     // Retrieve info of applications installed on external media that are currently
     // running.
     List<ApplicationInfo> getRunningExternalApplications();
+    @UnsupportedAppUsage
     void finishHeavyWeightApp();
     // A StrictMode violation to be handled.
+    @UnsupportedAppUsage
     void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask,
             in StrictMode.ViolationInfo crashInfo);
     boolean isTopActivityImmersive();
     void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message);
+    @UnsupportedAppUsage
     String getProviderMimeType(in Uri uri, int userId);
     // Cause the specified process to dump the specified heap.
     boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
             boolean runGc, in String path, in ParcelFileDescriptor fd,
             in RemoteCallback finishCallback);
+    @UnsupportedAppUsage
     boolean isUserRunning(int userid, int flags);
+    @UnsupportedAppUsage
     void setPackageScreenCompatMode(in String packageName, int mode);
+    @UnsupportedAppUsage
     boolean switchUser(int userid);
+    @UnsupportedAppUsage
     boolean removeTask(int taskId);
+    @UnsupportedAppUsage
     void registerProcessObserver(in IProcessObserver observer);
+    @UnsupportedAppUsage
     void unregisterProcessObserver(in IProcessObserver observer);
     boolean isIntentSenderTargetedToPackage(in IIntentSender sender);
+    @UnsupportedAppUsage
     void updatePersistentConfiguration(in Configuration values);
+    @UnsupportedAppUsage
     long[] getProcessPss(in int[] pids);
     void showBootMessage(in CharSequence msg, boolean always);
+    @UnsupportedAppUsage
     void killAllBackgroundProcesses();
     ContentProviderHolder getContentProviderExternal(in String name, int userId,
             in IBinder token, String tag);
     /** @deprecated - Use {@link #removeContentProviderExternalAsUser} which takes a user ID. */
+    @UnsupportedAppUsage
     void removeContentProviderExternal(in String name, in IBinder token);
     void removeContentProviderExternalAsUser(in String name, in IBinder token, int userId);
     // Get memory information about the calling process.
     void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
     boolean killProcessesBelowForeground(in String reason);
+    @UnsupportedAppUsage
     UserInfo getCurrentUser();
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
+    @UnsupportedAppUsage
     int getLaunchedFromUid(in IBinder activityToken);
+    @UnsupportedAppUsage
     void unstableProviderDied(in IBinder connection);
+    @UnsupportedAppUsage
     boolean isIntentSenderAnActivity(in IIntentSender sender);
     boolean isIntentSenderAForegroundService(in IIntentSender sender);
     boolean isIntentSenderABroadcast(in IIntentSender sender);
+    @UnsupportedAppUsage
     int startActivityAsUser(in IApplicationThread caller, in String callingPackage,
             in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
             int requestCode, int flags, in ProfilerInfo profilerInfo,
             in Bundle options, int userId);
+    @UnsupportedAppUsage
     int stopUser(int userid, boolean force, in IStopUserCallback callback);
+    @UnsupportedAppUsage
     void registerUserSwitchObserver(in IUserSwitchObserver observer, in String name);
     void unregisterUserSwitchObserver(in IUserSwitchObserver observer);
     int[] getRunningUserIds();
@@ -291,6 +349,7 @@
     // Deprecated - This method is only used by a few internal components and it will soon be
     // replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
     // No new code should be calling it.
+    @UnsupportedAppUsage
     void requestBugReport(int bugreportType);
 
     /**
@@ -319,15 +378,20 @@
      */
     void requestWifiBugReport(in String shareTitle, in String shareDescription);
 
+    @UnsupportedAppUsage
     Intent getIntentForIntentSender(in IIntentSender sender);
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
+    @UnsupportedAppUsage
     String getLaunchedFromPackage(in IBinder activityToken);
     void killUid(int appId, int userId, in String reason);
     void setUserIsMonkey(boolean monkey);
+    @UnsupportedAppUsage
     void hang(in IBinder who, boolean allowRestart);
 
+    @UnsupportedAppUsage
     List<ActivityManager.StackInfo> getAllStackInfos();
+    @UnsupportedAppUsage
     void moveTaskToStack(int taskId, int stackId, boolean toTop);
     /**
      * Resizes the input stack id to the given bounds.
@@ -343,60 +407,83 @@
      *                          default animation duration should be used.
      * @throws RemoteException
      */
+    @UnsupportedAppUsage
     void resizeStack(int stackId, in Rect bounds, boolean allowResizeInDockedMode,
             boolean preserveWindows, boolean animate, int animationDuration);
     void setFocusedStack(int stackId);
     ActivityManager.StackInfo getFocusedStackInfo();
+    @UnsupportedAppUsage
     void restart();
     void performIdleMaintenance();
     void appNotRespondingViaProvider(in IBinder connection);
+    @UnsupportedAppUsage
     Rect getTaskBounds(int taskId);
+    @UnsupportedAppUsage
     boolean setProcessMemoryTrimLevel(in String process, int uid, int level);
 
 
     // Start of L transactions
     String getTagForIntentSender(in IIntentSender sender, in String prefix);
+    @UnsupportedAppUsage
     boolean startUserInBackground(int userid);
+    @UnsupportedAppUsage
     boolean isInLockTaskMode();
+    @UnsupportedAppUsage
     void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver,
             in IRecentsAnimationRunner recentsAnimationRunner);
+    @UnsupportedAppUsage
     void cancelRecentsAnimation(boolean restoreHomeStackPosition);
+    @UnsupportedAppUsage
     int startActivityFromRecents(int taskId, in Bundle options);
+    @UnsupportedAppUsage
     void startSystemLockTaskMode(int taskId);
+    @UnsupportedAppUsage
     boolean isTopOfTask(in IBinder token);
     void bootAnimationComplete();
     int checkPermissionWithToken(in String permission, int pid, int uid,
             in IBinder callerToken);
+    @UnsupportedAppUsage
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
     void notifyCleartextNetwork(int uid, in byte[] firstPacket);
+    @UnsupportedAppUsage
     void setTaskResizeable(int taskId, int resizeableMode);
+    @UnsupportedAppUsage
     void resizeTask(int taskId, in Rect bounds, int resizeMode);
+    @UnsupportedAppUsage
     int getLockTaskModeState();
+    @UnsupportedAppUsage
     void setDumpHeapDebugLimit(in String processName, int uid, long maxMemSize,
             in String reportPackage);
     void dumpHeapFinished(in String path);
     void updateLockTaskPackages(int userId, in String[] packages);
     void noteAlarmStart(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
     void noteAlarmFinish(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
+    @UnsupportedAppUsage
     int getPackageProcessState(in String packageName, in String callingPackage);
     void updateDeviceOwner(in String packageName);
 
     // Start of N transactions
     // Start Binder transaction tracking for all applications.
+    @UnsupportedAppUsage
     boolean startBinderTracking();
     // Stop Binder transaction tracking for all applications and dump trace data to the given file
     // descriptor.
+    @UnsupportedAppUsage
     boolean stopBinderTrackingAndDump(in ParcelFileDescriptor fd);
     /**
      * Try to place task to provided position. The final position might be different depending on
      * current user and stacks state. The task will be moved to target stack if it's currently in
      * different stack.
      */
+    @UnsupportedAppUsage
     void positionTaskInStack(int taskId, int stackId, int position);
+    @UnsupportedAppUsage
     void suppressResizeConfigChanges(boolean suppress);
+    @UnsupportedAppUsage
     boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
     boolean isAppStartModeDisabled(int uid, in String packageName);
+    @UnsupportedAppUsage
     boolean unlockUser(int userid, in byte[] token, in byte[] secret,
             in IProgressListener listener);
     void killPackageDependents(in String packageName, int userId);
@@ -419,15 +506,18 @@
      *                                 stacks.
      * @throws RemoteException
      */
+    @UnsupportedAppUsage
     void resizeDockedStack(in Rect dockedBounds, in Rect tempDockedTaskBounds,
             in Rect tempDockedTaskInsetBounds,
             in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds);
+    @UnsupportedAppUsage
     void removeStack(int stackId);
     void makePackageIdle(String packageName, int userId);
     int getMemoryTrimLevel();
     boolean isVrModePackageEnabled(in ComponentName packageName);
     void notifyLockedProfile(int userId);
     void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options);
+    @UnsupportedAppUsage
     void sendIdleJobTrigger();
     int sendIntentSender(in IIntentSender target, in IBinder whitelistToken, int code,
             in Intent intent, in String resolvedType, in IIntentReceiver finishedReceiver,
@@ -449,6 +539,7 @@
     // Start of O transactions
     int restartUserInBackground(int userId);
     /** Cancels the window transitions for the given task. */
+    @UnsupportedAppUsage
     void cancelTaskWindowTransition(int taskId);
     /**
      * @param taskId the id of the task to retrieve the sAutoapshots for
@@ -456,6 +547,7 @@
      *                          a reduced resolution of it, which is much faster
      * @return a graphic buffer representing a screenshot of a task
      */
+    @UnsupportedAppUsage
     ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution);
     void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
     void setPersistentVrThread(int tid);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index b16188f..a6b76cb 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -473,4 +473,14 @@
      * contain one task.
      */
     void setDisplayToSingleTaskInstance(int displayId);
+
+    /**
+     * Restarts the activity by killing its process if it is visible. If the activity is not
+     * visible, the activity will not be restarted immediately and just keep the activity record in
+     * the stack. It also resets the current override configuration so the activity will use the
+     * configuration according to the latest state.
+     *
+     * @param activityToken The token of the target activity to restart.
+     */
+    void restartActivityProcessIfVisible(in IBinder activityToken);
 }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index ded4c49..6f624ee 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -29,13 +29,16 @@
  */
 interface IAlarmManager {
 	/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
+    @UnsupportedAppUsage
     void set(String callingPackage, int type, long triggerAtTime, long windowLength,
             long interval, int flags, in PendingIntent operation, in IAlarmListener listener,
             String listenerTag, in WorkSource workSource, in AlarmManager.AlarmClockInfo alarmClock);
+    @UnsupportedAppUsage
     boolean setTime(long millis);
     void setTimeZone(String zone);
     void remove(in PendingIntent operation, in IAlarmListener listener);
     long getNextWakeFromIdleTime();
+    @UnsupportedAppUsage
     AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
     long currentNetworkTimeMillis();
 }
diff --git a/core/java/android/app/IAppTask.aidl b/core/java/android/app/IAppTask.aidl
index 37fead9..61f6264 100644
--- a/core/java/android/app/IAppTask.aidl
+++ b/core/java/android/app/IAppTask.aidl
@@ -23,6 +23,7 @@
 /** @hide */
 interface IAppTask {
     void finishAndRemoveTask();
+    @UnsupportedAppUsage
     ActivityManager.RecentTaskInfo getTaskInfo();
     void moveToFront();
     int startActivity(IBinder whoThread, String callingPackage,
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index b8af898..3a09c4c 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -60,8 +60,10 @@
             in CompatibilityInfo compatInfo,
             int resultCode, in String data, in Bundle extras, boolean sync,
             int sendingUser, int processState);
+    @UnsupportedAppUsage
     void scheduleCreateService(IBinder token, in ServiceInfo info,
             in CompatibilityInfo compatInfo, int processState);
+    @UnsupportedAppUsage
     void scheduleStopService(IBinder token);
     void bindApplication(in String packageName, in ApplicationInfo info,
             in List<ProviderInfo> providers, in ComponentName testName,
@@ -77,8 +79,10 @@
     void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
     void updateTimeZone();
     void processInBackground();
+    @UnsupportedAppUsage
     void scheduleBindService(IBinder token,
             in Intent intent, boolean rebind, int processState);
+    @UnsupportedAppUsage
     void scheduleUnbindService(IBinder token,
             in Intent intent);
     void dumpService(in ParcelFileDescriptor fd, IBinder servicetoken,
@@ -106,6 +110,7 @@
     void updateHttpProxy();
     void setCoreSettings(in Bundle coreSettings);
     void updatePackageCompatibilityInfo(in String pkg, in CompatibilityInfo info);
+    @UnsupportedAppUsage
     void scheduleTrimMemory(int level);
     void dumpMemInfo(in ParcelFileDescriptor fd, in Debug.MemoryInfo mem, boolean checkin,
             boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
diff --git a/core/java/android/app/IAssistDataReceiver.aidl b/core/java/android/app/IAssistDataReceiver.aidl
index 2d5daf9..0d69838 100644
--- a/core/java/android/app/IAssistDataReceiver.aidl
+++ b/core/java/android/app/IAssistDataReceiver.aidl
@@ -21,6 +21,8 @@
 
 /** @hide */
 oneway interface IAssistDataReceiver {
+    @UnsupportedAppUsage
     void onHandleAssistData(in Bundle resultData);
+    @UnsupportedAppUsage
     void onHandleAssistScreenshot(in Bitmap screenshot);
 }
diff --git a/core/java/android/app/IInstrumentationWatcher.aidl b/core/java/android/app/IInstrumentationWatcher.aidl
index 6c8c4d6..df42dec 100644
--- a/core/java/android/app/IInstrumentationWatcher.aidl
+++ b/core/java/android/app/IInstrumentationWatcher.aidl
@@ -23,6 +23,7 @@
 /** @hide */
 interface IInstrumentationWatcher
 {
+    @UnsupportedAppUsage
     void instrumentationStatus(in ComponentName name, int resultCode,
             in Bundle results);
     void instrumentationFinished(in ComponentName name, int resultCode,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index df04a6b..e1da08b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -40,15 +40,19 @@
 /** {@hide} */
 interface INotificationManager
 {
+    @UnsupportedAppUsage
     void cancelAllNotifications(String pkg, int userId);
 
     void clearData(String pkg, int uid, boolean fromApp);
+    @UnsupportedAppUsage
     void enqueueToast(String pkg, ITransientNotification callback, int duration, int displayId);
+    @UnsupportedAppUsage
     void cancelToast(String pkg, ITransientNotification callback);
     void finishToken(String pkg, ITransientNotification callback);
 
     void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
             in Notification notification, int userId);
+    @UnsupportedAppUsage
     void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
 
     void setShowBadge(String pkg, int uid, boolean showBadge);
@@ -61,6 +65,7 @@
      */
     void setNotificationsEnabledWithImportanceLockForPackage(String pkg, int uid, boolean enabled);
 
+    @UnsupportedAppUsage
     boolean areNotificationsEnabledForPackage(String pkg, int uid);
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
@@ -102,7 +107,9 @@
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
+    @UnsupportedAppUsage
     StatusBarNotification[] getActiveNotifications(String callingPkg);
+    @UnsupportedAppUsage
     StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count);
 
     void registerListener(in INotificationListener listener, in ComponentName component, int userid);
@@ -157,7 +164,9 @@
     ComponentName getAllowedNotificationAssistantForUser(int userId);
     ComponentName getAllowedNotificationAssistant();
 
+    @UnsupportedAppUsage
     int getZenMode();
+    @UnsupportedAppUsage
     ZenModeConfig getZenModeConfig();
     NotificationManager.Policy getConsolidatedNotificationPolicy();
     oneway void setZenMode(int mode, in Uri conditionId, String reason);
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 0d09e4a..53f1a46 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -28,6 +28,7 @@
    SearchableInfo getSearchableInfo(in ComponentName launchActivity);
    List<SearchableInfo> getSearchablesInGlobalSearch();
    List<ResolveInfo> getGlobalSearchActivities();
+   @UnsupportedAppUsage
    ComponentName getGlobalSearchActivity();
    ComponentName getWebSearchActivity();
    void launchAssist(in Bundle args);
diff --git a/core/java/android/app/IServiceConnection.aidl b/core/java/android/app/IServiceConnection.aidl
index 97042aa..0115bcf 100644
--- a/core/java/android/app/IServiceConnection.aidl
+++ b/core/java/android/app/IServiceConnection.aidl
@@ -21,6 +21,7 @@
 
 /** @hide */
 oneway interface IServiceConnection {
+    @UnsupportedAppUsage
     void connected(in ComponentName name, IBinder service, boolean dead);
 }
 
diff --git a/core/java/android/app/IStopUserCallback.aidl b/core/java/android/app/IStopUserCallback.aidl
index 19ac1d5..d3c2ff7 100644
--- a/core/java/android/app/IStopUserCallback.aidl
+++ b/core/java/android/app/IStopUserCallback.aidl
@@ -22,6 +22,7 @@
  */
 interface IStopUserCallback
 {
+    @UnsupportedAppUsage
     void userStopped(int userId);
     void userStopAborted(int userId);
 }
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 8c85ad1..841ff6a 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -149,4 +149,16 @@
      * Called when a task snapshot got updated.
      */
     void onTaskSnapshotChanged(int taskId, in ActivityManager.TaskSnapshot snapshot);
+
+    /**
+     * Called when the resumed activity is in size compatibility mode and its override configuration
+     * is different from the current one of system.
+     *
+     * @param displayId Id of the display where the activity resides.
+     * @param activityToken Token of the size compatibility mode activity. It will be null when
+     *                      switching to a activity that is not in size compatibility mode or the
+     *                      configuration of the activity.
+     * @see com.android.server.wm.AppWindowToken#inSizeCompatMode
+     */
+    void onSizeCompatModeActivityChanged(int displayId, in IBinder activityToken);
 }
diff --git a/core/java/android/app/ITransientNotification.aidl b/core/java/android/app/ITransientNotification.aidl
index d5b3ed0..09a3ba0 100644
--- a/core/java/android/app/ITransientNotification.aidl
+++ b/core/java/android/app/ITransientNotification.aidl
@@ -19,6 +19,7 @@
 
 /** @hide */
 oneway interface ITransientNotification {
+    @UnsupportedAppUsage
     void show(IBinder windowToken);
     void hide();
 }
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 666f721..7f5350d 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -55,11 +55,13 @@
     /**
      * Set the live wallpaper. This only affects the system wallpaper.
      */
+    @UnsupportedAppUsage
     void setWallpaperComponent(in ComponentName name);
 
     /**
      * Get the wallpaper for a given user.
      */
+    @UnsupportedAppUsage
     ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb, int which,
             out Bundle outParams, int userId);
 
@@ -73,6 +75,7 @@
      * information about that wallpaper.  Otherwise, if it is a static image,
      * simply return null.
      */
+    @UnsupportedAppUsage
     WallpaperInfo getWallpaperInfo(int userId);
 
     /**
@@ -83,6 +86,7 @@
     /**
      * Return whether the current system wallpaper has the given name.
      */
+    @UnsupportedAppUsage
     boolean hasNamedWallpaper(String name);
 
     /**
@@ -94,11 +98,13 @@
     /**
      * Returns the desired minimum width for the wallpaper in a particular display.
      */
+    @UnsupportedAppUsage
     int getWidthHint(int displayId);
 
     /**
      * Returns the desired minimum height for the wallpaper in a particular display.
      */
+    @UnsupportedAppUsage
     int getHeightHint(int displayId);
 
     /**
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 17f645d..3ecb587 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -125,7 +125,7 @@
     public static final int RESULT_ALTERNATE = 1;
 
     /**
-     * @deprecated see {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)}
+     * @deprecated see {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)}
      *
      * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics
      * if enrolled) for the current user of the device. The caller is expected to launch this
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index e0cf561..03806fa 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -31,6 +31,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
+import android.content.LocusId;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -77,6 +78,7 @@
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.contentcapture.ContentCaptureContext;
 import android.widget.ProgressBar;
 import android.widget.RemoteViews;
 
@@ -1271,6 +1273,7 @@
     private long mTimeout;
 
     private String mShortcutId;
+    private LocusId mLocusId;
     private CharSequence mSettingsText;
 
     private BubbleMetadata mBubbleMetadata;
@@ -1629,6 +1632,7 @@
              *
              * @see Notification.Action#extras
              */
+            @NonNull
             public Builder addExtras(Bundle extras) {
                 if (extras != null) {
                     mExtras.putAll(extras);
@@ -1652,6 +1656,7 @@
              * @param remoteInput a {@link RemoteInput} to add to the action
              * @return this object for method chaining
              */
+            @NonNull
             public Builder addRemoteInput(RemoteInput remoteInput) {
                 if (mRemoteInputs == null) {
                     mRemoteInputs = new ArrayList<RemoteInput>();
@@ -1669,6 +1674,7 @@
              * @return this object for method chaining
              * The default value is {@code true}
              */
+            @NonNull
             public Builder setAllowGeneratedReplies(boolean allowGeneratedReplies) {
                 mAllowGeneratedReplies = allowGeneratedReplies;
                 return this;
@@ -1682,6 +1688,7 @@
              * {@code SEMANTIC_ACTION_} prefixes
              * @return this object for method chaining
              */
+            @NonNull
             public Builder setSemanticAction(@SemanticAction int semanticAction) {
                 mSemanticAction = semanticAction;
                 return this;
@@ -1692,6 +1699,7 @@
              * dependent on the notification message body. An example of a contextual action could
              * be an action opening a map application with an address shown in the notification.
              */
+            @NonNull
             public Builder setContextual(boolean isContextual) {
                 mIsContextual = isContextual;
                 return this;
@@ -1701,6 +1709,7 @@
              * Apply an extender to this action builder. Extenders may be used to add
              * metadata or change options on this builder.
              */
+            @NonNull
             public Builder extend(Extender extender) {
                 extender.extend(this);
                 return this;
@@ -1728,6 +1737,7 @@
              * object.
              * @return the built action
              */
+            @NonNull
             public Action build() {
                 checkContextualActionNullFields();
 
@@ -2267,6 +2277,10 @@
             mShortcutId = parcel.readString();
         }
 
+        if (parcel.readInt() != 0) {
+            mLocusId = LocusId.CREATOR.createFromParcel(parcel);
+        }
+
         mBadgeIcon = parcel.readInt();
 
         if (parcel.readInt() != 0) {
@@ -2390,6 +2404,7 @@
         that.mChannelId = this.mChannelId;
         that.mTimeout = this.mTimeout;
         that.mShortcutId = this.mShortcutId;
+        that.mLocusId = this.mLocusId;
         that.mBadgeIcon = this.mBadgeIcon;
         that.mSettingsText = this.mSettingsText;
         that.mGroupAlertBehavior = this.mGroupAlertBehavior;
@@ -2705,6 +2720,13 @@
             parcel.writeInt(0);
         }
 
+        if (mLocusId != null) {
+            parcel.writeInt(1);
+            mLocusId.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
         parcel.writeInt(mBadgeIcon);
 
         if (mSettingsText != null) {
@@ -3018,6 +3040,10 @@
             sb.append(" publicVersion=");
             sb.append(publicVersion.toString());
         }
+        if (this.mLocusId != null) {
+            sb.append(" locusId=");
+            sb.append(this.mLocusId); // LocusId.toString() is PII safe.
+        }
         sb.append(")");
         return sb.toString();
     }
@@ -3120,6 +3146,16 @@
         return mShortcutId;
     }
 
+    /**
+     * Gets the {@link LocusId} associated with this notification.
+     *
+     * <p>Used by the device's intelligence services to correlate objects (such as
+     * {@link ShortcutInfo} and {@link ContentCaptureContext}) that are correlated.
+     */
+    @Nullable
+    public LocusId getLocusId() {
+        return mLocusId;
+    }
 
     /**
      * Returns the settings text provided to {@link Builder#setSettingsText(CharSequence)}.
@@ -3478,6 +3514,19 @@
         }
 
         /**
+         * Sets the {@link LocusId} associated with this notification.
+         *
+         * <p>This method should be called when the {@link LocusId} is used in other places (such
+         * as {@link ShortcutInfo} and {@link ContentCaptureContext}) so the device's intelligence
+         * services can correlate them.
+         */
+        @NonNull
+        public Builder setLocusId(@Nullable LocusId locusId) {
+            mN.mLocusId = locusId;
+            return this;
+        }
+
+        /**
          * Sets which icon to display as a badge for this notification.
          *
          * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6ad6e38..edf86f9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1168,7 +1168,9 @@
      * matches the system intent action
      * TODO: STOPSHIP: Add correct intent
      * {@link android.provider.Settings#ACTION_MANAGE_DEFAULT_APPS_SETTINGS}.
+     * @hide
      */
+    @SystemApi
     public boolean isNotificationAssistantAccessGranted(@NonNull ComponentName assistant) {
         INotificationManager service = getService();
         try {
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 65859c7..14c58e7 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -1,18 +1,31 @@
 {
-  "imports": [
-    {
-      "path": "frameworks/base/services/core/java/com/android/server/am"
-    },
-    {
-      "path": "frameworks/base/services/core/java/com/android/server/wm"
-    }
-  ],
-  "presubmit": [
-      {
-        "name": "CtsFragmentTestCases"
-      },
-      {
-        "name": "CtsFragmentTestCasesSdk26"
-      }
-  ]
+    "imports": [
+        {
+            "path": "frameworks/base/services/core/java/com/android/server/am"
+        },
+        {
+            "path": "frameworks/base/services/core/java/com/android/server/wm"
+        }
+    ],
+    "presubmit": [
+        {
+            "name": "CtsFragmentTestCases"
+        },
+        {
+            "name": "CtsFragmentTestCasesSdk26"
+        },
+        {
+            "file_patterns": ["(/|^)AppOpsManager.java"],
+            "name": "CtsAppOpsTestCases"
+        },
+        {
+            "file_patterns": ["(/|^)AppOpsManager.java"],
+            "name": "FrameworksServicesTests",
+            "options": [
+                {
+                    "include-filter": "com.android.server.appop"
+                }
+            ]
+        }
+    ]
 }
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 47ad6d7..97b9176 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -19,6 +19,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager.TaskSnapshot;
 import android.content.ComponentName;
+import android.os.IBinder;
 import android.os.RemoteException;
 
 /**
@@ -155,4 +156,10 @@
     @UnsupportedAppUsage
     public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
     }
+
+    @Override
+    @UnsupportedAppUsage
+    public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken)
+            throws RemoteException {
+    }
 }
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index c2be4b0..e9b0175 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.slice.Slice;
 import android.content.ComponentName;
@@ -354,12 +355,17 @@
     
     /**
      * Returns an URI that provides a settings {@link Slice} for this wallpaper.
+     * The wallpaper should implement a SliceProvider associated with this URI.
+     * The system will display the Slice in the customization section while previewing the live
+     * wallpaper. Because this URI is accessible to other apps, it is recommended to protect it
+     * with the android.permission.BIND_WALLPAPER permission.
      *
      * <p>{@code null} will be returned if there is no settings Slice URI associated
      * with the wallpaper.
      *
      * @return The URI.
      */
+    @Nullable
     public Uri getSettingsSliceUri() {
         if (mSettingsSliceUri == null) {
             return null;
diff --git a/core/java/android/app/ZygotePreload.java b/core/java/android/app/ZygotePreload.java
index a295af3..eaaeb54 100644
--- a/core/java/android/app/ZygotePreload.java
+++ b/core/java/android/app/ZygotePreload.java
@@ -15,6 +15,7 @@
  */
 package android.app;
 
+import android.annotation.NonNull;
 import android.content.pm.ApplicationInfo;
 
 /**
@@ -27,8 +28,7 @@
  * {@link android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} attribute
  * of the &lt;service&gt; tag set to <code>true</code>.
  *
- * Note that this implementations of this class must provide a default constructor with no
- * arguments.
+ * Note that implementations of this class must provide a default constructor with no arguments.
  */
 public interface ZygotePreload {
     /**
@@ -38,5 +38,5 @@
      *
      * @param appInfo The ApplicationInfo object belonging to the application
      */
-    void doPreload(ApplicationInfo appInfo);
+    void doPreload(@NonNull ApplicationInfo appInfo);
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d593ad1..095d014 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3153,7 +3153,7 @@
      * {@link #PASSWORD_QUALITY_ALPHANUMERIC} with {@link #setPasswordQuality}.
      * <p>
      * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
-     * password is always treated as empty.
+     * password history length is always 0.
      * <p>
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
@@ -3191,6 +3191,9 @@
      * <p>
      * To disable password expiration, a value of 0 may be used for timeout.
      * <p>
+     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password expiration is always disabled.
+     * <p>
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this method; if it has
      * not, a security exception will be thrown.
@@ -3230,6 +3233,9 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password expiration is always disabled and this method always returns 0.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
      * @return The timeout for the given admin or the minimum of all timeouts
      */
@@ -3255,6 +3261,9 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * the password expiration for the parent profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password expiration is always disabled and this method always returns 0.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
      * @return The password expiration time, in milliseconds since epoch.
      */
@@ -3279,6 +3288,9 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password history length is always 0.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      * all admins.
      * @return The length of the password history
@@ -3306,7 +3318,7 @@
      * Return the maximum password length that the device supports for a
      * particular password quality.
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
-     * password is always empty.
+     * password is always empty and this method always returns 0.
      * @param quality The quality being interrogated.
      * @return Returns the maximum length that the user can enter.
      */
@@ -3362,7 +3374,7 @@
      * #getParentProfileInstance}.
      *
      * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
-     * password is always treated as empty.
+     * password is always empty and this method returns {@link #PASSWORD_COMPLEXITY_NONE}.
      *
      * @throws IllegalStateException if the user is not unlocked.
      * @throws SecurityException if the calling application does not have the permission
@@ -3437,6 +3449,8 @@
      * <p>
      * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN}
      * to be able to call this method; if it has not, a security exception will be thrown.
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password is always empty and this method always returns 0.
      *
      * @return The number of times user has entered an incorrect password since the last correct
      *         password entry.
@@ -3503,6 +3517,8 @@
      * This method can be called on the {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set a value on the parent
      * profile.
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password is always empty and this method has no effect - i.e. the policy is not set.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param num The number of failed password attempts at which point the device or profile will
@@ -3532,6 +3548,10 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * the value for the parent profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * password is always empty and this method returns a default value (0) indicating that the
+     * policy is not set.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      * all admins.
      */
@@ -3619,6 +3639,8 @@
      * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
      * that are not device owner or profile owner.  Once set, the password cannot be changed to null
      * or empty except by these admins.</em>
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, this
+     * methods does nothing.
      * <p>
      * The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has
@@ -3669,6 +3691,8 @@
      * will be stored on your server and who will need access to them. Tokens may be the subject of
      * legal access requests.
      * </em>
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, the
+     * reset token is not set and this method returns false.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param token a secure token a least 32-byte long, which must be generated by a
@@ -3693,6 +3717,10 @@
     /**
      * Called by a profile or device owner to revoke the current password reset token.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, this
+     * method has no effect - the reset token should not have been set in the first place - and
+     * false is returned.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return true if the operation is successful, false otherwise.
      * @throws SecurityException if admin is not a device or profile owner.
@@ -3713,6 +3741,9 @@
     /**
      * Called by a profile or device owner to check if the current reset password token is active.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
+     * false is always returned.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return true if the token is active, false otherwise.
      * @throws SecurityException if admin is not a device or profile owner.
@@ -3748,6 +3779,8 @@
      * <p>
      * Calling with a {@code null} or empty password will clear any existing PIN, pattern or
      * password if the current password constraints allow it.
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
+     * calling this methods has no effect - the password is always empty - and false is returned.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param password The new password for the user. {@code null} or empty clears the password.
@@ -3855,6 +3888,9 @@
      * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
      * profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
+     * calling this methods has no effect - i.e. the timeout is not set.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param timeoutMs The new timeout in milliseconds, after which the user will have to unlock
      *         with strong authentication method. A value of 0 means the admin is not participating
@@ -3887,6 +3923,9 @@
      * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
      * restrictions on the parent profile.
      *
+     * <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature,
+     * 0 is returned to indicate that no timeout is configured.
+     *
      * @param admin The name of the admin component to check, or {@code null} to aggregate
      *         across all participating admins.
      * @return The timeout in milliseconds or 0 if not configured for the provided admin.
@@ -6617,6 +6656,9 @@
      * This method can be called on the {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to set the configuration for
      * the parent profile.
+     * <p>
+     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, calling
+     * this method has no effect - no trust agent configuration will be set.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param target Component name of the agent to be configured.
@@ -6646,6 +6688,9 @@
      * This method can be called on the {@link DevicePolicyManager} instance returned by
      * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the configuration set
      * on the parent profile.
+     * <p>
+     * On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, null is
+     * always returned.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with. If null,
      * this function returns a list of configurations for all admins that declare
@@ -10587,18 +10632,18 @@
     }
 
     /**
-     * Whitelists a set of packages that are allowed to access cross-profile calendar APIs.
+     * Allows a set of packages to access cross-profile calendar APIs.
      *
      * <p>Called by a profile owner of a managed profile.
      *
-     * <p>Calling with a null value for the set disables the restriction so that all packages
-     * are allowed to access cross-profile calendar APIs. Calling with an empty set disallows
-     * all packages from accessing cross-profile calendar APIs. If this method isn't called,
-     * no package will be allowed to access cross-profile calendar APIs by default.
+     * <p>Calling with a {@code null} value for the set disables the restriction so that all
+     * packages are allowed to access cross-profile calendar APIs. Calling with an empty set
+     * disallows all packages from accessing cross-profile calendar APIs. If this method isn't
+     * called, no package is allowed to access cross-profile calendar APIs by default.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
-     * @param packageNames set of packages to be whitelisted.
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @param packageNames set of packages to be whitelisted
+     * @throws SecurityException if {@code admin} is not a profile owner
      *
      * @see #getCrossProfileCalendarPackages(ComponentName)
      */
@@ -10616,15 +10661,15 @@
     }
 
     /**
-     * Gets a set of package names that are whitelisted to access cross-profile calendar APIs.
+     * Gets a set of package names that are allowed to access cross-profile calendar APIs.
      *
      * <p>Called by a profile owner of a managed profile.
      *
-     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
-     * @return the set of names of packages that were previously whitelisted via
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with
+     * @return the set of names of packages that were previously allowed via
      * {@link #setCrossProfileCalendarPackages(ComponentName, Set)}, or an
-     * empty set if none have been whitelisted.
-     * @throws SecurityException if {@code admin} is not a profile owner.
+     * empty set if none have been allowed
+     * @throws SecurityException if {@code admin} is not a profile owner
      *
      * @see #setCrossProfileCalendarPackages(ComponentName, Set)
      */
@@ -10654,8 +10699,8 @@
      * that user, and get a {@link DevicePolicyManager} from this context.
      *
      * @param packageName the name of the package
-     * @return {@code true} if the package is allowed to access cross-profile calendar APIs.
-     * {@code false} otherwise.
+     * @return {@code true} if the package is allowed to access cross-profile calendar APIs,
+     * {@code false} otherwise
      *
      * @see #setCrossProfileCalendarPackages(ComponentName, Set)
      * @see #getCrossProfileCalendarPackages(ComponentName)
@@ -10675,15 +10720,15 @@
     }
 
     /**
-     * Gets a set of package names that are whitelisted to access cross-profile calendar APIs.
+     * Gets a set of package names that are allowed to access cross-profile calendar APIs.
      *
      * <p>To query for a specific user, use
      * {@link Context#createPackageContextAsUser(String, int, UserHandle)} to create a context for
      * that user, and get a {@link DevicePolicyManager} from this context.
      *
-     * @return the set of names of packages that were previously whitelisted via
+     * @return the set of names of packages that were previously allowed via
      * {@link #setCrossProfileCalendarPackages(ComponentName, Set)}, or an
-     * empty set if none have been whitelisted.
+     * empty set if none have been allowed
      *
      * @see #setCrossProfileCalendarPackages(ComponentName, Set)
      * @see #getCrossProfileCalendarPackages(ComponentName)
@@ -10775,12 +10820,12 @@
     /**
      * Starts an activity to view calendar events in the managed profile.
      *
-     * @param eventId the id of the event to be viewed.
-     * @param start the start time of the event.
-     * @param end the end time of the event.
-     * @param allDay if the event is an all-day event.
+     * @param eventId the id of the event to be viewed
+     * @param start the start time of the event
+     * @param end the end time of the event
+     * @param allDay if the event is an all-day event
      * @param flags flags to be set for the intent
-     * @return {@code true} if the activity is started successfully. {@code false} otherwise.
+     * @return {@code true} if the activity is started successfully, {@code false} otherwise
      *
      * @see CalendarContract#startViewCalendarEventInManagedProfile(Context, String, long, long,
      * long, boolean, int)
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9478a3c..3c389e4 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -124,6 +124,7 @@
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
     boolean isAdminActive(in ComponentName policyReceiver, int userHandle);
     List<ComponentName> getActiveAdmins(int userHandle);
+    @UnsupportedAppUsage
     boolean packageHasActiveAdmins(String packageName, int userHandle);
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);
     void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 8386c72..70ecdae 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -54,6 +54,7 @@
     /**
      * {@link android.app.backup.IBackupManager.dataChangedForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     void dataChanged(String packageName);
 
     /**
@@ -73,6 +74,7 @@
     /**
      * {@link android.app.backup.IBackupManager.clearBackupDataForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     void clearBackupData(String transportName, String packageName);
 
     /**
@@ -155,6 +157,7 @@
     /**
      * {@link android.app.backup.IBackupManager.setBackupEnabledForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     void setBackupEnabled(boolean isEnabled);
 
     /**
@@ -178,6 +181,7 @@
     /**
      * {@link android.app.backup.IBackupManager.setAutoRestoreForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     void setAutoRestore(boolean doAutoRestore);
 
     /**
@@ -194,6 +198,7 @@
     /**
      * {@link android.app.backup.IBackupManager.isBackupEnabledForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     boolean isBackupEnabled();
 
     /**
@@ -322,6 +327,7 @@
      * {@link android.app.backup.IBackupManager.acknowledgeFullBackupOrRestoreForUser} for the
      * calling user id.
      */
+    @UnsupportedAppUsage
     void acknowledgeFullBackupOrRestore(int token, boolean allow,
             in String curPassword, in String encryptionPassword,
             IFullBackupRestoreObserver observer);
@@ -371,6 +377,7 @@
     /**
      * {@link android.app.backup.IBackupManager.getCurrentTransportForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     String getCurrentTransport();
 
      /**
@@ -397,6 +404,7 @@
     /**
      * {@link android.app.backup.IBackupManager.listAllTransportsForUser} for the calling user id.
      */
+    @UnsupportedAppUsage
     String[] listAllTransports();
 
     /**
@@ -434,6 +442,7 @@
      * {@link android.app.backup.IBackupManager.selectBackupTransportForUser} for the calling user
      * id.
      */
+    @UnsupportedAppUsage
     String selectBackupTransport(String transport);
 
     /**
@@ -590,6 +599,7 @@
      * @param whichUser User handle of the defined user whose backup active state
      *     is being queried.
      */
+    @UnsupportedAppUsage
     boolean isBackupServiceActive(int whichUser);
 
     /**
diff --git a/core/java/android/app/contentsuggestions/ClassificationsRequest.java b/core/java/android/app/contentsuggestions/ClassificationsRequest.java
index 1b50015..2051a55 100644
--- a/core/java/android/app/contentsuggestions/ClassificationsRequest.java
+++ b/core/java/android/app/contentsuggestions/ClassificationsRequest.java
@@ -54,10 +54,10 @@
     }
 
     /**
-     * Return the request extras or {@code null} if there are none.
+     * Return the request extras, can be an empty bundle.
      */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
+    public @NonNull Bundle getExtras() {
+        return mExtras == null ? new Bundle() : mExtras;
     }
 
     @Override
@@ -103,7 +103,7 @@
         /**
          * Sets the request extras.
          */
-        public Builder setExtras(@NonNull Bundle extras) {
+        public @NonNull Builder setExtras(@NonNull Bundle extras) {
             mExtras = extras;
             return this;
         }
@@ -111,7 +111,7 @@
         /**
          * Builds a new request instance.
          */
-        public ClassificationsRequest build() {
+        public @NonNull ClassificationsRequest build() {
             return new ClassificationsRequest(mSelections, mExtras);
         }
     }
diff --git a/core/java/android/app/contentsuggestions/SelectionsRequest.java b/core/java/android/app/contentsuggestions/SelectionsRequest.java
index 257f98d..84f33b5 100644
--- a/core/java/android/app/contentsuggestions/SelectionsRequest.java
+++ b/core/java/android/app/contentsuggestions/SelectionsRequest.java
@@ -63,10 +63,10 @@
     }
 
     /**
-     * Return the request extras or {@code null} if there aren't any.
+     * Return the request extras, may be an empty bundle if there aren't any.
      */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
+    public @NonNull Bundle getExtras() {
+        return mExtras == null ? new Bundle() : mExtras;
     }
 
     @Override
@@ -118,7 +118,7 @@
         /**
          * Sets the request extras.
          */
-        public Builder setExtras(@NonNull Bundle extras) {
+        public @NonNull Builder setExtras(@NonNull Bundle extras) {
             mExtras = extras;
             return this;
         }
@@ -126,7 +126,7 @@
         /**
          * Sets the request interest point.
          */
-        public Builder setInterestPoint(@NonNull Point interestPoint) {
+        public @NonNull Builder setInterestPoint(@NonNull Point interestPoint) {
             mInterestPoint = interestPoint;
             return this;
         }
@@ -134,7 +134,7 @@
         /**
          * Builds a new request instance.
          */
-        public SelectionsRequest build() {
+        public @NonNull SelectionsRequest build() {
             return new SelectionsRequest(mTaskId, mInterestPoint, mExtras);
         }
     }
diff --git a/core/java/android/app/job/IJobCallback.aidl b/core/java/android/app/job/IJobCallback.aidl
index e7695e2..d281da0 100644
--- a/core/java/android/app/job/IJobCallback.aidl
+++ b/core/java/android/app/job/IJobCallback.aidl
@@ -36,6 +36,7 @@
      * @param ongoing True to indicate that the client is processing the job. False if the job is
      * complete
      */
+    @UnsupportedAppUsage
     void acknowledgeStartMessage(int jobId, boolean ongoing);
     /**
      * Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
@@ -43,14 +44,17 @@
      * @param jobId Unique integer used to identify this job.
      * @param reschedule Whether or not to reschedule this job.
      */
+    @UnsupportedAppUsage
     void acknowledgeStopMessage(int jobId, boolean reschedule);
     /*
      * Called to deqeue next work item for the job.
      */
+    @UnsupportedAppUsage
     JobWorkItem dequeueWork(int jobId);
     /*
      * Called to report that job has completed processing a work item.
      */
+    @UnsupportedAppUsage
     boolean completeWork(int jobId, int workId);
     /*
      * Tell the job manager that the client is done with its execution, so that it can go on to
@@ -59,5 +63,6 @@
      * @param jobId Unique integer used to identify this job.
      * @param reschedule Whether or not to reschedule this job.
      */
+    @UnsupportedAppUsage
     void jobFinished(int jobId, boolean reschedule);
 }
diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl
index 7f55d29..22ad252 100644
--- a/core/java/android/app/job/IJobService.aidl
+++ b/core/java/android/app/job/IJobService.aidl
@@ -26,7 +26,9 @@
  */
 oneway interface IJobService {
     /** Begin execution of application's job. */
+    @UnsupportedAppUsage
     void startJob(in JobParameters jobParams);
     /** Stop execution of application's job. */
+    @UnsupportedAppUsage
     void stopJob(in JobParameters jobParams);
 }
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index c665cb23..f91d878 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -187,6 +187,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1;
 
     /**
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index b1500c1..62b24e9 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -28,8 +28,10 @@
  * {@hide}
  */
 interface IUsageStatsManager {
+    @UnsupportedAppUsage
     ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
+    @UnsupportedAppUsage
     ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
     ParceledListSlice queryEventStats(int bucketType, long beginTime, long endTime,
@@ -38,7 +40,9 @@
     UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
     UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage);
     UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage);
+    @UnsupportedAppUsage
     void setAppInactive(String packageName, boolean inactive, int userId);
+    @UnsupportedAppUsage
     boolean isAppInactive(String packageName, int userId);
     void whitelistAppTemporarily(String packageName, long duration, int userId);
     void onCarrierPrivilegedAppsChanged();
@@ -56,7 +60,7 @@
             in PendingIntent sessionEndCallbackIntent, String callingPackage);
     void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage);
     void registerAppUsageLimitObserver(int observerId, in String[] packages, long timeLimitMs,
-            in PendingIntent callback, String callingPackage);
+            long timeRemainingMs, in PendingIntent callback, String callingPackage);
     void unregisterAppUsageLimitObserver(int observerId, String callingPackage);
     void reportUsageStart(in IBinder activity, String token, String callingPackage);
     void reportPastUsageStart(in IBinder activity, String token, long timeAgoMs,
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index d34e6d3..cee6b87 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -35,6 +35,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -738,6 +739,23 @@
     }
 
     /**
+     * @deprecated use
+     * {@link #registerAppUsageLimitObserver(int, String[], Duration, Duration, PendingIntent)}.
+     *
+     * @removed
+     * @hide
+     */
+    @Deprecated
+    @UnsupportedAppUsage
+    // STOPSHIP b/126917290: remove this method once ag/6591106 is merged and it's not being used.
+    public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
+            long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) {
+        final Duration timeLimitDuration = Duration.ofMillis(timeUnit.toMillis(timeLimit));
+        registerAppUsageLimitObserver(observerId, observedEntities,
+                timeLimitDuration, timeLimitDuration, callbackIntent);
+    }
+
+    /**
      * Register a usage limit observer that receives a callback on the provided intent when the
      * sum of usages of apps and tokens in the provided {@code observedEntities} array exceeds the
      * {@code timeLimit} specified. The structure of a token is a {@link String} with the reporting
@@ -759,19 +777,21 @@
      * @see android.content.pm.LauncherApps#getAppUsageLimit
      *
      * @param observerId A unique id associated with the group of apps to be monitored. There can
-     *                  be multiple groups with common packages and different time limits.
+     *                   be multiple groups with common packages and different time limits.
      * @param observedEntities The list of packages and token to observe for usage time. Cannot be
      *                         null and must include at least one package or token.
      * @param timeLimit The total time the set of apps can be in the foreground before the
-     *                  callbackIntent is delivered. Must be at least one minute. Note: a limit of
-     *                  0 can be set to indicate that the user has already exhausted the limit for
-     *                  a group, in which case, the given {@code callbackIntent} will be ignored.
-     * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
+     *                  {@code callbackIntent} is delivered. Must be at least one minute.
+     * @param timeRemaining The remaining time the set of apps can be in the foreground before the
+     *                      {@code callbackIntent} is delivered. Must be greater than
+     *                      {@code timeLimit}. Note: a limit of 0 can be set to indicate that the
+     *                      user has already exhausted the limit for a group, in which case,
+     *                      the given {@code callbackIntent} will be ignored.
      * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
      *                       exceeded by the group of apps. The delivered Intent will also contain
      *                       the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
      *                       {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is
-     *                       being registered with a {@code timeLimit} of 0.
+     *                       being registered with a {@code timeRemaining} of 0.
      * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
      *                           permissions.
      * @hide
@@ -781,10 +801,12 @@
             android.Manifest.permission.SUSPEND_APPS,
             android.Manifest.permission.OBSERVE_APP_USAGE})
     public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
-            long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) {
+            @NonNull Duration timeLimit, @NonNull Duration timeRemaining,
+            @Nullable PendingIntent callbackIntent) {
         try {
             mService.registerAppUsageLimitObserver(observerId, observedEntities,
-                    timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName());
+                    timeLimit.toMillis(), timeRemaining.toMillis(), callbackIntent,
+                    mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index 0d25f4d..f59bc98 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -16,12 +16,15 @@
 package android.content;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArraySet;
 import android.util.Log;
 import android.view.autofill.AutofillManager;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
 
 import java.io.PrintWriter;
 
@@ -51,8 +54,13 @@
     /**
      * Whether package is whitelisted for augmented autofill.
      */
-    public boolean augmentedEnabled;
-    // TODO(b/123100824): add (optional) list of activities
+    public boolean augmentedAutofillEnabled;
+
+    /**
+     * List of whitelisted activities.
+     */
+    @Nullable
+    public ArraySet<ComponentName> whitelistedActivitiesForAugmentedAutofill;
 
     public AutofillOptions(int loggingLevel, boolean compatModeEnabled) {
         this.loggingLevel = loggingLevel;
@@ -60,6 +68,20 @@
     }
 
     /**
+     * Returns whether activity is whitelisted for augmented autofill.
+     */
+    public boolean isAugmentedAutofillEnabled(@NonNull Context context) {
+        if (!augmentedAutofillEnabled) return false;
+
+        final ContentCaptureClient contentCaptureClient = context.getContentCaptureClient();
+        if (contentCaptureClient == null) return false;
+
+        final ComponentName component = contentCaptureClient.contentCaptureClientGetComponentName();
+        return whitelistedActivitiesForAugmentedAutofill == null
+                || whitelistedActivitiesForAugmentedAutofill.contains(component);
+    }
+
+    /**
      * @hide
      */
     @TestApi
@@ -78,7 +100,7 @@
 
         final AutofillOptions options = new AutofillOptions(
                 AutofillManager.FLAG_ADD_CLIENT_VERBOSE, /* compatModeAllowed= */ true);
-        options.augmentedEnabled = true;
+        options.augmentedAutofillEnabled = true;
         // Always log, as it's used by test only
         Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
 
@@ -87,15 +109,19 @@
 
     @Override
     public String toString() {
-        return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode="
-                + compatModeEnabled + ", augmentedEnabled=" + augmentedEnabled + "]";
+        return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode=" + compatModeEnabled
+                + ", augmentedAutofillEnabled=" + augmentedAutofillEnabled + "]";
     }
 
     /** @hide */
     public void dumpShort(@NonNull PrintWriter pw) {
         pw.print("logLvl="); pw.print(loggingLevel);
         pw.print(", compatMode="); pw.print(compatModeEnabled);
-        pw.print(", augmented="); pw.print(augmentedEnabled);
+        pw.print(", augmented="); pw.print(augmentedAutofillEnabled);
+        if (whitelistedActivitiesForAugmentedAutofill != null) {
+            pw.print(", whitelistedActivitiesForAugmentedAutofill=");
+            pw.print(whitelistedActivitiesForAugmentedAutofill);
+        }
     }
 
     @Override
@@ -107,7 +133,8 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(loggingLevel);
         parcel.writeBoolean(compatModeEnabled);
-        parcel.writeBoolean(augmentedEnabled);
+        parcel.writeBoolean(augmentedAutofillEnabled);
+        parcel.writeArraySet(whitelistedActivitiesForAugmentedAutofill);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<AutofillOptions> CREATOR =
@@ -118,7 +145,9 @@
                     final int loggingLevel = parcel.readInt();
                     final boolean compatMode = parcel.readBoolean();
                     final AutofillOptions options = new AutofillOptions(loggingLevel, compatMode);
-                    options.augmentedEnabled = parcel.readBoolean();
+                    options.augmentedAutofillEnabled = parcel.readBoolean();
+                    options.whitelistedActivitiesForAugmentedAutofill =
+                            (ArraySet<ComponentName>) parcel.readArraySet(null);
                     return options;
                 }
 
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index ca657b1..9948338 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -800,5 +800,6 @@
         }
     }
 
+    @UnsupportedAppUsage
     private IBinder mRemote;
 }
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 1e4b1e7..fa85f0a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -623,7 +623,7 @@
     }
 
     /** {@hide} */
-    public static ContentResolver wrap(@NonNull ContentInterface wrapped) {
+    public static @NonNull ContentResolver wrap(@NonNull ContentInterface wrapped) {
         Preconditions.checkNotNull(wrapped);
 
         return new ContentResolver(null, wrapped) {
@@ -654,7 +654,7 @@
      * Create a {@link ContentResolver} instance that redirects all its methods
      * to the given {@link ContentProvider}.
      */
-    public static ContentResolver wrap(@NonNull ContentProvider wrapped) {
+    public static @NonNull ContentResolver wrap(@NonNull ContentProvider wrapped) {
         return wrap((ContentInterface) wrapped);
     }
 
@@ -662,7 +662,7 @@
      * Create a {@link ContentResolver} instance that redirects all its methods
      * to the given {@link ContentProviderClient}.
      */
-    public static ContentResolver wrap(@NonNull ContentProviderClient wrapped) {
+    public static @NonNull ContentResolver wrap(@NonNull ContentProviderClient wrapped) {
         return wrap((ContentInterface) wrapped);
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index beb1fb6..41995288 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -69,6 +69,7 @@
 import android.view.ViewDebug;
 import android.view.WindowManager;
 import android.view.autofill.AutofillManager.AutofillClient;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
 import android.view.textclassifier.TextClassificationManager;
 
 import java.io.File;
@@ -5343,6 +5344,14 @@
     /**
      * @hide
      */
+    @Nullable
+    public ContentCaptureClient getContentCaptureClient() {
+        return null;
+    }
+
+    /**
+     * @hide
+     */
     public final boolean isAutofillCompatibilityEnabled() {
         final AutofillOptions options = getAutofillOptions();
         return options != null && options.compatModeEnabled;
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 9f6e236..a34a995 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -61,6 +61,7 @@
      */
     void sync(in SyncRequest request, String callingPackage);
     void syncAsUser(in SyncRequest request, int userId, String callingPackage);
+    @UnsupportedAppUsage
     void cancelSync(in Account account, String authority, in ComponentName cname);
     void cancelSyncAsUser(in Account account, String authority, in ComponentName cname, int userId);
 
@@ -118,6 +119,7 @@
      * Check if this account/provider is syncable.
      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
      */
+    @UnsupportedAppUsage
     int getIsSyncable(in Account account, String providerName);
     int getIsSyncableAsUser(in Account account, String providerName, int userId);
 
@@ -128,9 +130,11 @@
     void setIsSyncable(in Account account, String providerName, int syncable);
     void setIsSyncableAsUser(in Account account, String providerName, int syncable, int userId);
 
+    @UnsupportedAppUsage
     void setMasterSyncAutomatically(boolean flag);
     void setMasterSyncAutomaticallyAsUser(boolean flag, int userId);
 
+    @UnsupportedAppUsage
     boolean getMasterSyncAutomatically();
     boolean getMasterSyncAutomaticallyAsUser(int userId);
 
@@ -141,6 +145,7 @@
      * Returns the types of the SyncAdapters that are registered with the system.
      * @return Returns the types of the SyncAdapters that are registered with the system.
      */
+    @UnsupportedAppUsage
     SyncAdapterType[] getSyncAdapterTypes();
     SyncAdapterType[] getSyncAdapterTypesAsUser(int userId);
 
@@ -154,6 +159,7 @@
      * @param cname component to identify sync service, must be null if account/providerName are
      * non-null.
      */
+    @UnsupportedAppUsage
     boolean isSyncActive(in Account account, String authority, in ComponentName cname);
 
     /**
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
index 3d92723..2b45021 100644
--- a/core/java/android/content/IIntentReceiver.aidl
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -27,6 +27,7 @@
  * {@hide}
  */
 oneway interface IIntentReceiver {
+    @UnsupportedAppUsage
     void performReceive(in Intent intent, int resultCode, String data,
             in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
 }
diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl
index 0eb581e..9242d02 100644
--- a/core/java/android/content/ISyncAdapter.aidl
+++ b/core/java/android/content/ISyncAdapter.aidl
@@ -32,6 +32,7 @@
      *
      * @param cb If called back with {@code false} accounts are not synced.
      */
+    @UnsupportedAppUsage
     void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb);
 
     /**
@@ -44,6 +45,7 @@
      * @param account the account that should be synced
      * @param extras SyncAdapter-specific parameters
      */
+    @UnsupportedAppUsage
     void startSync(ISyncContext syncContext, String authority,
       in Account account, in Bundle extras);
 
@@ -52,5 +54,6 @@
      * after the ISyncContext.onFinished() for that sync was called.
      * @param syncContext the ISyncContext that was passed to {@link #startSync}
      */
+    @UnsupportedAppUsage
     void cancelSync(ISyncContext syncContext);
 }
diff --git a/core/java/android/content/ISyncServiceAdapter.aidl b/core/java/android/content/ISyncServiceAdapter.aidl
index d419307..29f3a40 100644
--- a/core/java/android/content/ISyncServiceAdapter.aidl
+++ b/core/java/android/content/ISyncServiceAdapter.aidl
@@ -35,11 +35,13 @@
      * @param extras SyncAdapter-specific parameters.
      *
      */
+    @UnsupportedAppUsage
     void startSync(ISyncContext syncContext, in Bundle extras);
 
     /**
      * Cancel the currently ongoing sync.
      */
+    @UnsupportedAppUsage
     void cancelSync(ISyncContext syncContext);
 
 }
diff --git a/core/java/android/content/ISyncStatusObserver.aidl b/core/java/android/content/ISyncStatusObserver.aidl
index eb26845..64bf3bd 100644
--- a/core/java/android/content/ISyncStatusObserver.aidl
+++ b/core/java/android/content/ISyncStatusObserver.aidl
@@ -20,5 +20,6 @@
  * @hide
  */
 oneway interface ISyncStatusObserver {
+    @UnsupportedAppUsage
     void onStatusChanged(int which);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d3b8e29..0715572 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2124,6 +2124,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES)
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES =
             "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java
index 2142cf3..c67ff7c 100644
--- a/core/java/android/content/LocusId.java
+++ b/core/java/android/content/LocusId.java
@@ -16,7 +16,6 @@
 package android.content;
 
 import android.annotation.NonNull;
-import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -34,28 +33,30 @@
 // TODO(b/123577059): make sure this is well documented and understandable
 public final class LocusId implements Parcelable {
 
-    private final Uri mUri;
+    private final String mId;
 
     /**
      * Default constructor.
+     *
+     * @throws IllegalArgumentException if {@code id} is empty or {@code null}.
      */
-    public LocusId(@NonNull Uri uri) {
-        mUri = Preconditions.checkNotNull(uri);
+    public LocusId(@NonNull String id) {
+        mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty");
     }
 
     /**
-     * Gets the {@code uri} associated with the locus.
+     * Gets the {@code id} associated with the locus.
      */
     @NonNull
-    public Uri getUri() {
-        return mUri;
+    public String getId() {
+        return mId;
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((mUri == null) ? 0 : mUri.hashCode());
+        result = prime * result + ((mId == null) ? 0 : mId.hashCode());
         return result;
     }
 
@@ -65,26 +66,27 @@
         if (obj == null) return false;
         if (getClass() != obj.getClass()) return false;
         final LocusId other = (LocusId) obj;
-        if (mUri == null) {
-            if (other.mUri != null) return false;
+        if (mId == null) {
+            if (other.mId != null) return false;
         } else {
-            if (!mUri.equals(other.mUri)) return false;
+            if (!mId.equals(other.mId)) return false;
         }
         return true;
     }
 
     @Override
     public String toString() {
-        return "LocusId[uri=" + getSanitizedUri() + "]";
+        return "LocusId[" + getSanitizedId() + "]";
     }
 
     /** @hide */
     public void dump(@NonNull PrintWriter pw) {
-        pw.print("uri:"); pw.println(getSanitizedUri());
+        pw.print("id:"); pw.println(getSanitizedId());
     }
 
-    private String getSanitizedUri() {
-        final int size = mUri.toString().length();
+    @NonNull
+    private String getSanitizedId() {
+        final int size = mId.length();
         return size + "_chars";
     }
 
@@ -94,8 +96,8 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mUri, flags);
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mId);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<LocusId> CREATOR =
@@ -103,9 +105,8 @@
 
         @NonNull
         @Override
-        public LocusId createFromParcel(Parcel source) {
-            final Uri uri = source.readParcelable(null);
-            return new LocusId(uri);
+        public LocusId createFromParcel(Parcel parcel) {
+            return new LocusId(parcel.readString());
         }
 
         @NonNull
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 5b3c9dd..722c128 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -37,6 +37,7 @@
      *         mapped to lists of overlays; if no overlays exist for the
      *         requested user, an empty map is returned.
      */
+    @UnsupportedAppUsage
     Map getAllOverlays(in int userId);
 
     /**
@@ -60,6 +61,7 @@
      * @return The OverlayInfo for the overlay package; or null if no such
      *         overlay package exists.
      */
+    @UnsupportedAppUsage
     OverlayInfo getOverlayInfo(in String packageName, in int userId);
 
     /**
diff --git a/core/java/android/content/pm/IPackageDataObserver.aidl b/core/java/android/content/pm/IPackageDataObserver.aidl
index d010ee4..926ecda 100644
--- a/core/java/android/content/pm/IPackageDataObserver.aidl
+++ b/core/java/android/content/pm/IPackageDataObserver.aidl
@@ -24,5 +24,6 @@
  * {@hide}
  */
 oneway interface IPackageDataObserver {
+    @UnsupportedAppUsage
     void onRemoveCompleted(in String packageName, boolean succeeded);
 }
diff --git a/core/java/android/content/pm/IPackageDeleteObserver.aidl b/core/java/android/content/pm/IPackageDeleteObserver.aidl
index 2e2d16e..faae81e 100644
--- a/core/java/android/content/pm/IPackageDeleteObserver.aidl
+++ b/core/java/android/content/pm/IPackageDeleteObserver.aidl
@@ -23,6 +23,7 @@
  * {@hide}
  */
 oneway interface IPackageDeleteObserver {
+    @UnsupportedAppUsage
     void packageDeleted(in String packageName, in int returnCode);
 }
 
diff --git a/core/java/android/content/pm/IPackageDeleteObserver2.aidl b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
index bff3baa..ea80967 100644
--- a/core/java/android/content/pm/IPackageDeleteObserver2.aidl
+++ b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
@@ -21,5 +21,6 @@
 /** {@hide} */
 oneway interface IPackageDeleteObserver2 {
     void onUserActionRequired(in Intent intent);
+    @UnsupportedAppUsage
     void onPackageDeleted(String packageName, int returnCode, String msg);
 }
diff --git a/core/java/android/content/pm/IPackageInstallObserver2.aidl b/core/java/android/content/pm/IPackageInstallObserver2.aidl
index bb5f22a..ed2eb7d 100644
--- a/core/java/android/content/pm/IPackageInstallObserver2.aidl
+++ b/core/java/android/content/pm/IPackageInstallObserver2.aidl
@@ -25,6 +25,7 @@
  * @hide
  */
 oneway interface IPackageInstallObserver2 {
+    @UnsupportedAppUsage
     void onUserActionRequired(in Intent intent);
 
     /**
@@ -42,5 +43,6 @@
      * </tr>
      * </table>
      */
+    @UnsupportedAppUsage
     void onPackageInstalled(String basePackageName, int returnCode, String msg, in Bundle extras);
 }
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 0cf83fd..8e84079 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -47,6 +47,7 @@
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
 
+    @UnsupportedAppUsage
     void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags,
             in IntentSender statusReceiver, int userId);
 
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index 974eb1e..ee26500 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -18,9 +18,14 @@
 
 /** {@hide} */
 oneway interface IPackageInstallerCallback {
+    @UnsupportedAppUsage
     void onSessionCreated(int sessionId);
+    @UnsupportedAppUsage
     void onSessionBadgingChanged(int sessionId);
+    @UnsupportedAppUsage
     void onSessionActiveChanged(int sessionId, boolean active);
+    @UnsupportedAppUsage
     void onSessionProgressChanged(int sessionId, float progress);
+    @UnsupportedAppUsage
     void onSessionFinished(int sessionId, boolean success);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index dcbb4ac..fd3529b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -63,45 +63,60 @@
  */
 interface IPackageManager {
     void checkPackageStartable(String packageName, int userId);
+    @UnsupportedAppUsage
     boolean isPackageAvailable(String packageName, int userId);
+    @UnsupportedAppUsage
     PackageInfo getPackageInfo(String packageName, int flags, int userId);
     PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
             int flags, int userId);
+    @UnsupportedAppUsage
     int getPackageUid(String packageName, int flags, int userId);
     int[] getPackageGids(String packageName, int flags, int userId);
 
+    @UnsupportedAppUsage
     String[] currentToCanonicalPackageNames(in String[] names);
+    @UnsupportedAppUsage
     String[] canonicalToCurrentPackageNames(in String[] names);
 
     PermissionInfo getPermissionInfo(String name, String packageName, int flags);
 
     ParceledListSlice queryPermissionsByGroup(String group, int flags);
 
+    @UnsupportedAppUsage
     PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
 
     ParceledListSlice getAllPermissionGroups(int flags);
 
+    @UnsupportedAppUsage
     ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
 
+    @UnsupportedAppUsage
     ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
 
     boolean activitySupportsIntent(in ComponentName className, in Intent intent,
             String resolvedType);
 
+    @UnsupportedAppUsage
     ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     int checkPermission(String permName, String pkgName, int userId);
 
     int checkUidPermission(String permName, int uid);
 
+    @UnsupportedAppUsage
     boolean addPermission(in PermissionInfo info);
 
+    @UnsupportedAppUsage
     void removePermission(String name);
 
+    @UnsupportedAppUsage
     void grantRuntimePermission(String packageName, String permissionName, int userId);
 
     void revokeRuntimePermission(String packageName, String permissionName, int userId);
@@ -120,33 +135,43 @@
 
     boolean isProtectedBroadcast(String actionName);
 
+    @UnsupportedAppUsage
     int checkSignatures(String pkg1, String pkg2);
 
+    @UnsupportedAppUsage
     int checkUidSignatures(int uid1, int uid2);
 
     List<String> getAllPackages();
 
+    @UnsupportedAppUsage
     String[] getPackagesForUid(int uid);
 
+    @UnsupportedAppUsage
     String getNameForUid(int uid);
     String[] getNamesForUids(in int[] uids);
 
+    @UnsupportedAppUsage
     int getUidForSharedUser(String sharedUserName);
 
+    @UnsupportedAppUsage
     int getFlagsForUid(int uid);
 
     int getPrivateFlagsForUid(int uid);
 
+    @UnsupportedAppUsage
     boolean isUidPrivileged(int uid);
 
+    @UnsupportedAppUsage
     String[] getAppOpPermissionPackages(String permissionName);
 
+    @UnsupportedAppUsage
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
     ResolveInfo findPersistentPreferredActivity(in Intent intent, int userId);
 
     boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
 
+    @UnsupportedAppUsage
     ParceledListSlice queryIntentActivities(in Intent intent,
             String resolvedType, int flags, int userId);
 
@@ -173,6 +198,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
+    @UnsupportedAppUsage
     ParceledListSlice getInstalledPackages(int flags, in int userId);
 
     /**
@@ -190,6 +216,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
+    @UnsupportedAppUsage
     ParceledListSlice getInstalledApplications(int flags, int userId);
 
     /**
@@ -210,20 +237,24 @@
      * @param outInfo Filled in with a list of the ProviderInfo for each
      *                name in 'outNames'.
      */
+    @UnsupportedAppUsage
     void querySyncProviders(inout List<String> outNames,
             inout List<ProviderInfo> outInfo);
 
     ParceledListSlice queryContentProviders(
             String processName, int uid, int flags, String metaDataKey);
 
+    @UnsupportedAppUsage
     InstrumentationInfo getInstrumentationInfo(
             in ComponentName className, int flags);
 
+    @UnsupportedAppUsage
     ParceledListSlice queryInstrumentation(
             String targetPackage, int flags);
 
     void finishPackageInstall(int token, boolean didLaunch);
 
+    @UnsupportedAppUsage
     void setInstallerPackageName(in String targetPackage, in String installerPackageName);
 
     void setApplicationCategoryHint(String packageName, int categoryHint, String callerPackageName);
@@ -243,24 +274,30 @@
     void deletePackageVersioned(in VersionedPackage versionedPackage,
             IPackageDeleteObserver2 observer, int userId, int flags);
 
+    @UnsupportedAppUsage
     String getInstallerPackageName(in String packageName);
 
     void resetApplicationPreferences(int userId);
 
+    @UnsupportedAppUsage
     ResolveInfo getLastChosenActivity(in Intent intent,
             String resolvedType, int flags);
 
+    @UnsupportedAppUsage
     void setLastChosenActivity(in Intent intent, String resolvedType, int flags,
             in IntentFilter filter, int match, in ComponentName activity);
 
     void addPreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity, int userId);
 
+    @UnsupportedAppUsage
     void replacePreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity, int userId);
 
+    @UnsupportedAppUsage
     void clearPackagePreferredActivities(String packageName);
 
+    @UnsupportedAppUsage
     int getPreferredActivities(out List<IntentFilter> outFilters,
             out List<ComponentName> outActivities, String packageName);
 
@@ -300,6 +337,7 @@
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
      */
+     @UnsupportedAppUsage
      ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
 
     void setHomeActivity(in ComponentName className, int userId);
@@ -307,23 +345,27 @@
     /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
+    @UnsupportedAppUsage
     void setComponentEnabledSetting(in ComponentName componentName,
             in int newState, in int flags, int userId);
 
     /**
      * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
      */
+    @UnsupportedAppUsage
     int getComponentEnabledSetting(in ComponentName componentName, int userId);
 
     /**
      * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
      */
+    @UnsupportedAppUsage
     void setApplicationEnabledSetting(in String packageName, in int newState, int flags,
             int userId, String callingPackage);
 
     /**
      * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
      */
+    @UnsupportedAppUsage
     int getApplicationEnabledSetting(in String packageName, int userId);
 
     /**
@@ -341,6 +383,7 @@
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
+    @UnsupportedAppUsage
     void setPackageStoppedState(String packageName, boolean stopped, int userId);
 
     /**
@@ -396,6 +439,7 @@
      * files need to be deleted
      * @param observer a callback used to notify when the deletion is finished.
      */
+    @UnsupportedAppUsage
     void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
 
     /**
@@ -436,6 +480,7 @@
      * Get a list of shared libraries that are available on the
      * system.
      */
+    @UnsupportedAppUsage
     String[] getSystemSharedLibraryNames();
 
     /**
@@ -447,8 +492,10 @@
     boolean hasSystemFeature(String name, int version);
 
     void enterSafeMode();
+    @UnsupportedAppUsage
     boolean isSafeMode();
     void systemReady();
+    @UnsupportedAppUsage
     boolean hasSystemUidErrors();
 
     /**
@@ -570,9 +617,11 @@
     int movePackage(in String packageName, in String volumeUuid);
     int movePrimaryStorage(in String volumeUuid);
 
+    @UnsupportedAppUsage
     boolean addPermissionAsync(in PermissionInfo info);
 
     boolean setInstallLocation(int loc);
+    @UnsupportedAppUsage
     int getInstallLocation();
 
     int installExistingPackageAsUser(String packageName, int userId, int installFlags,
@@ -600,17 +649,21 @@
     boolean isPermissionEnforced(String permission);
 
     /** Reflects current DeviceStorageMonitorService state */
+    @UnsupportedAppUsage
     boolean isStorageLow();
 
+    @UnsupportedAppUsage
     boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
     boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
 
     void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden);
     boolean setSystemAppInstallState(String packageName, boolean installed, int userId);
 
+    @UnsupportedAppUsage
     IPackageInstaller getPackageInstaller();
 
     boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
+    @UnsupportedAppUsage
     boolean getBlockUninstallForUser(String packageName, int userId);
 
     KeySet getKeySetByAlias(String packageName, String alias);
@@ -631,6 +684,7 @@
 
     boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId);
 
+    @UnsupportedAppUsage
     String getPermissionControllerPackageName();
 
     ParceledListSlice getInstantApps(int userId);
@@ -647,7 +701,9 @@
      */
     void setUpdateAvailable(String packageName, boolean updateAvaialble);
 
+    @UnsupportedAppUsage
     String getServicesSystemSharedLibraryPackageName();
+    @UnsupportedAppUsage
     String getSharedSystemSharedLibraryPackageName();
 
     ChangedPackages getChangedPackages(int sequenceNumber, int userId);
diff --git a/core/java/android/content/pm/IPackageStatsObserver.aidl b/core/java/android/content/pm/IPackageStatsObserver.aidl
index ede4d1d..559a035 100644
--- a/core/java/android/content/pm/IPackageStatsObserver.aidl
+++ b/core/java/android/content/pm/IPackageStatsObserver.aidl
@@ -26,5 +26,6 @@
  */
 oneway interface IPackageStatsObserver {
     
+    @UnsupportedAppUsage
     void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 38ea43e..0cc5f39 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -792,7 +792,7 @@
      *
      * @return an {@link AppUsageLimit} object describing the app time limit containing
      * the given package with the smallest time remaining, or {@code null} if none exist.
-     * @throws SecurityException when the caller is not the active launcher.
+     * @throws SecurityException when the caller is not the recents app.
      */
     @Nullable
     public LauncherApps.AppUsageLimit getAppUsageLimit(@NonNull String packageName,
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 0304f19..7de8105 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1343,6 +1343,7 @@
          */
         public boolean areHiddenOptionsSet() {
             return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
+                    | PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE
                     | PackageManager.INSTALL_DONT_KILL_APP
                     | PackageManager.INSTALL_INSTANT_APP
                     | PackageManager.INSTALL_FULL_APP
@@ -2129,7 +2130,7 @@
          * Text description of the error code returned by {@code getStagedSessionErrorCode}, or
          * empty string if no error was encountered.
          */
-        public String getStagedSessionErrorMessage() {
+        public @NonNull String getStagedSessionErrorMessage() {
             checkSessionIsStaged();
             return mStagedSessionErrorMessage;
         }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a5464c2..c133fba 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -721,6 +721,7 @@
             INSTALL_VIRTUAL_PRELOAD,
             INSTALL_APEX,
             INSTALL_ENABLE_ROLLBACK,
+            INSTALL_RESPECT_ALLOW_DOWNGRADE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallFlags {}
@@ -865,6 +866,15 @@
      */
     public static final int INSTALL_DISABLE_VERIFICATION = 0x00080000;
 
+    /**
+     * Flag parameter for {@link #installPackage} to indicate that
+     * {@link #INSTALL_ALLOW_DOWNGRADE} should be respected.
+     *
+     * @hide
+     */
+    // TODO(b/127322579): rename
+    public static final int INSTALL_RESPECT_ALLOW_DOWNGRADE = 0x00100000;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
             DONT_KILL_APP
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a006f23..c4a574a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -45,6 +45,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityTaskManager;
@@ -3260,10 +3261,21 @@
     private boolean parsePermissionGroup(Package owner, int flags, Resources res,
             XmlResourceParser parser, String[] outError)
             throws XmlPullParserException, IOException {
-        PermissionGroup perm = new PermissionGroup(owner);
-
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup);
+
+        int requestDetailResourceId = sa.getResourceId(
+                com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
+        int backgroundRequestResourceId = sa.getResourceId(
+                com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
+                0);
+        int backgroundRequestDetailResourceId = sa.getResourceId(
+                com.android.internal.R.styleable
+                        .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
+
+        PermissionGroup perm = new PermissionGroup(owner, requestDetailResourceId,
+                backgroundRequestResourceId, backgroundRequestDetailResourceId);
+
         if (!parsePackageItemInfo(owner, perm.info, outError,
                 "<permission-group>", sa, true /*nameRequired*/,
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_name,
@@ -3282,14 +3294,6 @@
                 0);
         perm.info.requestRes = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_request, 0);
-        perm.info.requestDetailResourceId = sa.getResourceId(
-                com.android.internal.R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
-        perm.info.backgroundRequestResourceId = sa.getResourceId(
-                com.android.internal.R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
-                0);
-        perm.info.backgroundRequestDetailResourceId = sa.getResourceId(
-                com.android.internal.R.styleable
-                        .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
         perm.info.flags = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
         perm.info.priority = sa.getInt(
@@ -3315,7 +3319,20 @@
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestPermission);
 
-        Permission perm = new Permission(owner);
+        String backgroundPermission = null;
+        if (sa.hasValue(
+                com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) {
+            if ("android".equals(owner.packageName)) {
+                backgroundPermission = sa.getNonResourceString(
+                        com.android.internal.R.styleable
+                                .AndroidManifestPermission_backgroundPermission);
+            } else {
+                Slog.w(TAG, owner.packageName + " defines a background permission. Only the "
+                        + "'android' package can do that.");
+            }
+        }
+
+        Permission perm = new Permission(owner, backgroundPermission);
         if (!parsePackageItemInfo(owner, perm.info, outError,
                 "<permission>", sa, true /*nameRequired*/,
                 com.android.internal.R.styleable.AndroidManifestPermission_name,
@@ -3344,19 +3361,6 @@
         perm.info.requestRes = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestPermission_request, 0);
 
-        if (sa.hasValue(
-                com.android.internal.R.styleable.AndroidManifestPermission_backgroundPermission)) {
-            if ("android".equals(owner.packageName)) {
-                perm.info.backgroundPermission = sa.getNonResourceString(
-                        com.android.internal.R.styleable
-                                .AndroidManifestPermission_backgroundPermission);
-            } else {
-                Slog.w(TAG, owner.packageName + " defines permission '" + perm.info.name
-                        + "' with a background permission. Only the 'android' package can do "
-                        + "that.");
-            }
-        }
-
         perm.info.protectionLevel = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestPermission_protectionLevel,
                 PermissionInfo.PROTECTION_NORMAL);
@@ -3399,7 +3403,7 @@
     private boolean parsePermissionTree(Package owner, Resources res,
             XmlResourceParser parser, String[] outError)
         throws XmlPullParserException, IOException {
-        Permission perm = new Permission(owner);
+        Permission perm = new Permission(owner, (String) null);
 
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestPermissionTree);
@@ -7609,9 +7613,12 @@
         @UnsupportedAppUsage
         public PermissionGroup group;
 
-        public Permission(Package _owner) {
-            super(_owner);
-            info = new PermissionInfo();
+        /**
+         * @hide
+         */
+        public Permission(Package owner, @Nullable String backgroundPermission) {
+            super(owner);
+            info = new PermissionInfo(backgroundPermission);
         }
 
         @UnsupportedAppUsage
@@ -7676,9 +7683,12 @@
         @UnsupportedAppUsage
         public final PermissionGroupInfo info;
 
-        public PermissionGroup(Package _owner) {
-            super(_owner);
-            info = new PermissionGroupInfo();
+        public PermissionGroup(Package owner, @StringRes int requestDetailResourceId,
+                @StringRes int backgroundRequestResourceId,
+                @StringRes int backgroundRequestDetailResourceId) {
+            super(owner);
+            info = new PermissionGroupInfo(requestDetailResourceId, backgroundRequestResourceId,
+                    backgroundRequestDetailResourceId);
         }
 
         public PermissionGroup(Package _owner, PermissionGroupInfo _info) {
diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java
index 3a87eca..e65e742 100644
--- a/core/java/android/content/pm/PermissionGroupInfo.java
+++ b/core/java/android/content/pm/PermissionGroupInfo.java
@@ -16,12 +16,20 @@
 
 package android.content.pm;
 
+import static android.content.res.Resources.ID_NULL;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Information you can retrieve about a particular security permission
  * group known to the system.  This corresponds to information collected from the
@@ -33,7 +41,7 @@
      * permission's description.  From the "description" attribute or,
      * if not set, 0.
      */
-    public int descriptionRes;
+    public @StringRes int descriptionRes;
 
     /**
      * A string resource identifier (in the package's resources) used to request the permissions.
@@ -54,7 +62,7 @@
      * @hide
      */
     @SystemApi
-    public @StringRes int requestDetailResourceId;
+    public final @StringRes int requestDetailResourceId;
 
     /**
      * A string resource identifier (in the package's resources) used when requesting background
@@ -66,7 +74,7 @@
      * @hide
      */
     @SystemApi
-    public @StringRes int backgroundRequestResourceId;
+    public final @StringRes int backgroundRequestResourceId;
 
     /**
      * A string resource identifier (in the package's resources) used as subtitle when requesting
@@ -78,7 +86,7 @@
      * @hide
      */
     @SystemApi
-    public @StringRes int backgroundRequestDetailResourceId;
+    public final @StringRes int backgroundRequestDetailResourceId;
 
     /**
      * The description string provided in the AndroidManifest file, if any.  You
@@ -86,7 +94,7 @@
      * is in a resource.  You probably want
      * {@link PermissionInfo#loadDescription} instead.
      */
-    public CharSequence nonLocalizedDescription;
+    public @Nullable CharSequence nonLocalizedDescription;
 
     /**
      * Flag for {@link #flags}, corresponding to <code>personalInfo</code>
@@ -94,21 +102,48 @@
      */
     public static final int FLAG_PERSONAL_INFO = 1<<0;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            FLAG_PERSONAL_INFO,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Flags {}
+
     /**
      * Additional flags about this group as given by
      * {@link android.R.attr#permissionGroupFlags}.
      */
-    public int flags;
+    public @Flags int flags;
 
     /**
      * Prioritization of this group, for visually sorting with other groups.
      */
     public int priority;
 
-    public PermissionGroupInfo() {
+    /**
+     * @hide
+     */
+    public PermissionGroupInfo(@StringRes int requestDetailResourceId,
+            @StringRes int backgroundRequestResourceId,
+            @StringRes int backgroundRequestDetailResourceId) {
+        this.requestDetailResourceId = requestDetailResourceId;
+        this.backgroundRequestResourceId = backgroundRequestResourceId;
+        this.backgroundRequestDetailResourceId = backgroundRequestDetailResourceId;
     }
 
-    public PermissionGroupInfo(PermissionGroupInfo orig) {
+    /**
+     * @deprecated Should only be created by the system.
+     */
+    @Deprecated
+    public PermissionGroupInfo() {
+        this(ID_NULL, ID_NULL, ID_NULL);
+    }
+
+    /**
+     * @deprecated Should only be created by the system.
+     */
+    @Deprecated
+    public PermissionGroupInfo(@NonNull PermissionGroupInfo orig) {
         super(orig);
         descriptionRes = orig.descriptionRes;
         requestRes = orig.requestRes;
@@ -131,7 +166,7 @@
      * @return Returns a CharSequence containing the permission's description.
      * If there is no description, null is returned.
      */
-    public CharSequence loadDescription(PackageManager pm) {
+    public @Nullable CharSequence loadDescription(@NonNull PackageManager pm) {
         if (nonLocalizedDescription != null) {
             return nonLocalizedDescription;
         }
@@ -166,7 +201,7 @@
         dest.writeInt(priority);
     }
 
-    public static final @android.annotation.NonNull Creator<PermissionGroupInfo> CREATOR =
+    public static final @NonNull Creator<PermissionGroupInfo> CREATOR =
             new Creator<PermissionGroupInfo>() {
         public PermissionGroupInfo createFromParcel(Parcel source) {
             return new PermissionGroupInfo(source);
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index b093867..6a41f33 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -17,6 +17,9 @@
 package android.content.pm;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -300,7 +303,7 @@
      * The group this permission is a part of, as per
      * {@link android.R.attr#permissionGroup}.
      */
-    public String group;
+    public @Nullable String group;
 
     /**
      * Flag for {@link #flags}, corresponding to <code>costsMoney</code>
@@ -322,18 +325,27 @@
      */
     public static final int FLAG_INSTALLED = 1<<30;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            FLAG_COSTS_MONEY,
+            FLAG_INSTALLED,
+            FLAG_REMOVED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Flags {}
+
     /**
      * Additional flags about this permission as given by
      * {@link android.R.attr#permissionFlags}.
      */
-    public int flags;
+    public @Flags int flags;
 
     /**
      * A string resource identifier (in the package's resources) of this
      * permission's description.  From the "description" attribute or,
      * if not set, 0.
      */
-    public int descriptionRes;
+    public @StringRes int descriptionRes;
 
     /**
      * A string resource identifier (in the package's resources) used to request the permissions.
@@ -342,7 +354,7 @@
      * @hide
      */
     @SystemApi
-    public int requestRes;
+    public @StringRes int requestRes;
 
     /**
      * Some permissions only grant access while the app is in foreground. Some of these permissions
@@ -357,7 +369,7 @@
      */
     @SystemApi
     @TestApi
-    public String backgroundPermission;
+    public final @Nullable String backgroundPermission;
 
     /**
      * The description string provided in the AndroidManifest file, if any.  You
@@ -365,7 +377,7 @@
      * is in a resource.  You probably want
      * {@link PermissionInfo#loadDescription} instead.
      */
-    public CharSequence nonLocalizedDescription;
+    public @Nullable CharSequence nonLocalizedDescription;
 
     /** @hide */
     public static int fixProtectionLevel(int level) {
@@ -383,7 +395,7 @@
 
     /** @hide */
     @UnsupportedAppUsage
-    public static String protectionToString(int level) {
+    public static @NonNull String protectionToString(int level) {
         String protLevel = "????";
         switch (level & PROTECTION_MASK_BASE) {
             case PermissionInfo.PROTECTION_DANGEROUS:
@@ -456,10 +468,26 @@
         return protLevel;
     }
 
-    public PermissionInfo() {
+    /**
+     * @hide
+     */
+    public PermissionInfo(@Nullable String backgroundPermission) {
+        this.backgroundPermission = backgroundPermission;
     }
 
-    public PermissionInfo(PermissionInfo orig) {
+    /**
+     * @deprecated Should only be created by the system.
+     */
+    @Deprecated
+    public PermissionInfo() {
+        this((String) null);
+    }
+
+    /**
+     * @deprecated Should only be created by the system.
+     */
+    @Deprecated
+    public PermissionInfo(@NonNull PermissionInfo orig) {
         super(orig);
         protectionLevel = orig.protectionLevel;
         flags = orig.flags;
@@ -481,7 +509,7 @@
      * @return Returns a CharSequence containing the permission's description.
      * If there is no description, null is returned.
      */
-    public CharSequence loadDescription(PackageManager pm) {
+    public @Nullable CharSequence loadDescription(@NonNull PackageManager pm) {
         if (nonLocalizedDescription != null) {
             return nonLocalizedDescription;
         }
@@ -551,7 +579,7 @@
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
     }
 
-    public static final @android.annotation.NonNull Creator<PermissionInfo> CREATOR =
+    public static final @NonNull Creator<PermissionInfo> CREATOR =
         new Creator<PermissionInfo>() {
         @Override
         public PermissionInfo createFromParcel(Parcel source) {
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index d5273db..7b61807 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -22,11 +22,13 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
+import android.app.Notification;
 import android.app.Person;
 import android.app.TaskStackBuilder;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.LocusId;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -41,6 +43,7 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+import android.view.contentcapture.ContentCaptureContext;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
@@ -354,6 +357,9 @@
     @Nullable
     private Person[] mPersons;
 
+    @Nullable
+    private LocusId mLocusId;
+
     private int mRank;
 
     /**
@@ -415,6 +421,8 @@
         }
         mRank = b.mRank;
         mExtras = b.mExtras;
+        mLocusId = b.mLocusId;
+
         updateTimestamp();
     }
 
@@ -521,6 +529,7 @@
         mFlags = source.mFlags;
         mLastChangedTimestamp = source.mLastChangedTimestamp;
         mDisabledReason = source.mDisabledReason;
+        mLocusId = source.mLocusId;
 
         // Just always keep it since it's cheep.
         mIconResId = source.mIconResId;
@@ -876,6 +885,10 @@
         if (source.mExtras != null) {
             mExtras = source.mExtras;
         }
+
+        if (source.mLocusId != null) {
+            mLocusId = source.mLocusId;
+        }
     }
 
     /**
@@ -941,6 +954,8 @@
 
         private PersistableBundle mExtras;
 
+        private LocusId mLocusId;
+
         /**
          * Old style constructor.
          * @hide
@@ -973,6 +988,19 @@
         }
 
         /**
+         * Sets the {@link LocusId} associated with this shortcut.
+         *
+         * <p>This method should be called when the {@link LocusId} is used in other places (such
+         * as {@link Notification} and {@link ContentCaptureContext}) so the device's intelligence
+         * services can correlate them.
+         */
+        @NonNull
+        public Builder setLocusId(@NonNull LocusId locusId) {
+            mLocusId = Preconditions.checkNotNull(locusId, "locusId cannot be null");
+            return this;
+        }
+
+        /**
          * Sets the target activity.  A shortcut will be shown along with this activity's icon
          * on the launcher.
          *
@@ -1295,6 +1323,17 @@
     }
 
     /**
+     * Gets the {@link LocusId} associated with this shortcut.
+     *
+     * <p>Used by the device's intelligence services to correlate objects (such as
+     * {@link Notification} and {@link ContentCaptureContext}) that are correlated.
+     */
+    @Nullable
+    public LocusId getLocusId() {
+        return mLocusId;
+    }
+
+    /**
      * Return the package name of the publisher app.
      */
     @NonNull
@@ -1999,6 +2038,7 @@
         }
 
         mPersons = source.readParcelableArray(cl, Person.class);
+        mLocusId = source.readParcelable(cl);
     }
 
     @Override
@@ -2048,6 +2088,7 @@
         }
 
         dest.writeParcelableArray(mPersons, flags);
+        dest.writeParcelable(mLocusId, flags);
     }
 
     public static final @android.annotation.NonNull Creator<ShortcutInfo> CREATOR =
@@ -2263,6 +2304,10 @@
             sb.append(mBitmapPath);
         }
 
+        if (mLocusId != null) {
+            sb.append("locusId="); sb.append(mLocusId); // LocusId.toString() is PII-safe.
+        }
+
         sb.append("}");
         return sb.toString();
     }
@@ -2276,7 +2321,7 @@
             Set<String> categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras,
             long lastChangedTimestamp,
             int flags, int iconResId, String iconResName, String bitmapPath, int disabledReason,
-            Person[] persons) {
+            Person[] persons, LocusId locusId) {
         mUserId = userId;
         mId = id;
         mPackageName = packageName;
@@ -2303,5 +2348,6 @@
         mBitmapPath = bitmapPath;
         mDisabledReason = disabledReason;
         mPersons = persons;
+        mLocusId = locusId;
     }
 }
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 1cb7eb0..27c04b4 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -128,7 +128,7 @@
 
     /**
      * The device does not have pin, pattern, or password set up. See
-     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} and
      * {@link KeyguardManager#isDeviceSecure()}
      */
     int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 459ec62..3602a33 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -136,7 +136,7 @@
 
     /**
      * The device does not have pin, pattern, or password set up. See
-     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} and
      * {@link KeyguardManager#isDeviceSecure()}
      */
     public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 6cbab47..b025508 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -121,7 +121,7 @@
 
     /**
      * The device does not have pin, pattern, or password set up. See
-     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} and
      * {@link KeyguardManager#isDeviceSecure()}
      * @hide
      */
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index c64e48f..e751b2c 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -204,7 +204,7 @@
          * "Cancel" button, but may be also used to show an alternative method for authentication,
          * such as screen that asks for a backup password.
          *
-         * Note that this should not be set if {@link #setAllowDeviceCredential(boolean)
+         * Note that this should not be set if {@link #setDeviceCredentialAllowed(boolean)}(boolean)
          * is set to true.
          *
          * @param text
@@ -245,7 +245,7 @@
          *
          * @param requireConfirmation
          */
-        @NonNull public Builder setRequireConfirmation(boolean requireConfirmation) {
+        @NonNull public Builder setConfirmationRequired(boolean requireConfirmation) {
             mBundle.putBoolean(KEY_REQUIRE_CONFIRMATION, requireConfirmation);
             return this;
         }
@@ -261,12 +261,12 @@
          * Note that {@link #setNegativeButton(CharSequence, Executor,
          * DialogInterface.OnClickListener)} should not be set if this is set to true.
          *
-         * @param enable When true, the prompt will fall back to ask for the user's device
+         * @param allowed When true, the prompt will fall back to ask for the user's device
          *               credentials (PIN, pattern, or password).
          * @return
          */
-        @NonNull public Builder setAllowDeviceCredential(boolean enable) {
-            mBundle.putBoolean(KEY_ALLOW_DEVICE_CREDENTIAL, enable);
+        @NonNull public Builder setDeviceCredentialAllowed(boolean allowed) {
+            mBundle.putBoolean(KEY_ALLOW_DEVICE_CREDENTIAL, allowed);
             return this;
         }
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a25bbdb..f8b2a5b 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -85,7 +85,8 @@
          *
          * @hide
          */
-        public Key(String name, String fallbackName, Class<T> type) {
+        @UnsupportedAppUsage
+        public Key(@NonNull String name, @NonNull String fallbackName, @NonNull Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name,  fallbackName, type);
         }
 
@@ -97,7 +98,7 @@
          * they may be useful for testing purposes and for defining custom camera
          * characteristics.</p>
          */
-        public Key(String name, Class<T> type) {
+        public Key(@NonNull String name, @NonNull Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name,  type);
         }
 
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 536c2e1..23401432 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -678,6 +678,31 @@
         public void onCameraUnavailable(@NonNull String cameraId) {
             // default empty implementation
         }
+
+        /**
+         * Notify registered clients about a change in the camera access priorities.
+         *
+         * <p>Notification that camera access priorities have changed and the camera may
+         * now be openable. An application that was previously denied camera access due to
+         * a higher-priority user already using the camera, or that was disconnected from an
+         * active camera session due to a higher-priority user trying to open the camera,
+         * should try to open the camera again if it still wants to use it.  Note that
+         * multiple applications may receive this callback at the same time, and only one of
+         * them will succeed in opening the camera in practice, depending on exact access
+         * priority levels and timing. This method is useful in cases where multiple
+         * applications may be in the resumed state at the same time, and the user switches
+         * focus between them, or if the current camera-using application moves between
+         * full-screen and Picture-in-Picture (PiP) states. In such cases, the camera
+         * available/unavailable callbacks will not be invoked, but another application may
+         * now have higher priority for camera access than the current camera-using
+         * application.</p>
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         */
+        public void onCameraAccessPrioritiesChanged() {
+            // default empty implementation
+        }
     }
 
     /**
@@ -1098,6 +1123,22 @@
             }
         }
 
+        private void postSingleAccessPriorityChangeUpdate(final AvailabilityCallback callback,
+                final Executor executor) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                executor.execute(
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            callback.onCameraAccessPrioritiesChanged();
+                        }
+                    });
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         private void postSingleUpdate(final AvailabilityCallback callback, final Executor executor,
                 final String id, final int status) {
             if (isAvailable(status)) {
@@ -1347,6 +1388,19 @@
             }
         }
 
+        @Override
+        public void onCameraAccessPrioritiesChanged() {
+            synchronized (mLock) {
+                final int callbackCount = mCallbackMap.size();
+                for (int i = 0; i < callbackCount; i++) {
+                    Executor executor = mCallbackMap.valueAt(i);
+                    final AvailabilityCallback callback = mCallbackMap.keyAt(i);
+
+                    postSingleAccessPriorityChangeUpdate(callback, executor);
+                }
+            }
+        }
+
         /**
          * Try to connect to camera service after some delay if any client registered camera
          * availability callback or torch status callback.
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index da1bfe4..eddfd7d 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -120,7 +120,7 @@
          * {@link CaptureRequest}, and not need to construct their own Key objects. However, they
          * may be useful for testing purposes and for defining custom capture request fields.</p>
          */
-        public Key(String name, Class<T> type) {
+        public Key(@NonNull String name, @NonNull Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, type);
         }
 
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 53d4dd3..7382ac4 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -89,7 +89,8 @@
          *
          * @hide
          */
-        public Key(String name, String fallbackName, Class<T> type) {
+        @UnsupportedAppUsage
+        public Key(@NonNull String name, @NonNull String fallbackName, @NonNull Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, fallbackName, type);
         }
 
@@ -100,7 +101,7 @@
          * {@link CaptureResult}, and not need to construct their own Key objects. However, they may
          * be useful for testing purposes and for defining custom capture result fields.</p>
          */
-        public Key(String name, Class<T> type) {
+        public Key(@NonNull String name, @NonNull Class<T> type) {
             mKey = new CameraMetadataNative.Key<T>(name, type);
         }
 
@@ -4251,6 +4252,7 @@
      * @see CaptureResult#SENSOR_TIMESTAMP
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Key<long[]> STATISTICS_OIS_TIMESTAMPS =
             new Key<long[]>("android.statistics.oisTimestamps", long[].class);
 
@@ -4270,6 +4272,7 @@
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Key<float[]> STATISTICS_OIS_X_SHIFTS =
             new Key<float[]>("android.statistics.oisXShifts", float[].class);
 
@@ -4289,6 +4292,7 @@
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      * @hide
      */
+    @UnsupportedAppUsage
     public static final Key<float[]> STATISTICS_OIS_Y_SHIFTS =
             new Key<float[]>("android.statistics.oisYShifts", float[].class);
 
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index ac44fe9..ea63776 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -185,6 +185,21 @@
     }
 
     /**
+     * Check if specified UID's content is present on display and should be granted access to it.
+     *
+     * @param uid UID to be checked.
+     * @param displayId id of the display where presence of the content is checked.
+     * @return {@code true} if UID is present on display, {@code false} otherwise.
+     */
+    public boolean isUidPresentOnDisplay(int uid, int displayId) {
+        try {
+            return mDm.isUidPresentOnDisplay(uid, displayId);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets information about a logical display.
      *
      * The display metrics may be adjusted to provide compatibility
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 43ea682..8231985 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -187,14 +187,6 @@
     public abstract void setDisplayAccessUIDs(SparseArray<IntArray> displayAccessUIDs);
 
     /**
-     * Check if specified UID's content is present on display and should be granted access to it.
-     *
-     * @param uid UID to be checked.
-     * @param displayId id of the display where presence of the content is checked.
-     * */
-    public abstract boolean isUidPresentOnDisplay(int uid, int displayId);
-
-    /**
      * Persist brightness slider events and ambient brightness stats.
      */
     public abstract void persistBrightnessTrackerState();
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index edd2051..0143c91 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -34,6 +34,8 @@
     DisplayInfo getDisplayInfo(int displayId);
     int[] getDisplayIds();
 
+    boolean isUidPresentOnDisplay(int uid, int displayId);
+
     void registerCallback(in IDisplayManagerCallback callback);
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 55b340f..139a5ee 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -286,14 +286,15 @@
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public void setFeature(int feature, boolean enabled, byte[] token) {
+    public boolean setFeature(int feature, boolean enabled, byte[] token) {
         if (mService != null) {
             try {
-                mService.setFeature(feature, enabled, token);
+                return mService.setFeature(feature, enabled, token);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
+        return false;
     }
 
     /**
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 9609e99..5043d4c 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -98,7 +98,7 @@
     // Enumerate all faces
     void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
 
-    int setFeature(int feature, boolean enabled, in byte [] token);
+    boolean setFeature(int feature, boolean enabled, in byte [] token);
 
     boolean getFeature(int feature);
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1312f18..0497f8c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2681,12 +2681,39 @@
         }
     }
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            TETHER_ERROR_NO_ERROR,
+            TETHER_ERROR_PROVISION_FAILED,
+            TETHER_ERROR_ENTITLEMENT_UNKONWN,
+    })
+    public @interface EntitlementResultCode {
+    }
+
     /**
-     * Callback for use with {@link #getLatestTetheringEntitlementValue} to find out whether
+     * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
      * entitlement succeeded.
      * @hide
      */
     @SystemApi
+    public interface OnTetheringEntitlementResultListener  {
+        /**
+         * Called to notify entitlement result.
+         *
+         * @param resultCode an int value of entitlement result. It may be one of
+         *         {@link #TETHER_ERROR_NO_ERROR},
+         *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
+         *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
+         */
+        void onEntitlementResult(@EntitlementResultCode int resultCode);
+    }
+
+    /**
+     * @removed
+     * @deprecated This API would be removed when all of caller has been updated.
+     * */
+    @Deprecated
     public abstract static class TetheringEntitlementValueListener  {
         /**
          * Called to notify entitlement result.
@@ -2712,14 +2739,43 @@
      *         {@link #TETHERING_USB}, or
      *         {@link #TETHERING_BLUETOOTH}.
      * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
-     * @param listener an {@link TetheringEntitlementValueListener} which will be called to notify
-     *         the caller of the result of entitlement check. The listener may be called zero or
-     *         one time.
-     * @param handler {@link Handler} to specify the thread upon which the listener will be invoked.
+     * @param executor the executor on which callback will be invoked.
+     * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
+     *         notify the caller of the result of entitlement check. The listener may be called zero
+     *         or one time.
      * {@hide}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull final OnTetheringEntitlementResultListener listener) {
+        Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null.");
+        ResultReceiver wrappedListener = new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                Binder.withCleanCallingIdentity(() ->
+                            executor.execute(() -> {
+                                listener.onEntitlementResult(resultCode);
+                            }));
+            }
+        };
+
+        try {
+            String pkgName = mContext.getOpPackageName();
+            Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName);
+            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
+                    showEntitlementUi, pkgName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @removed
+     * @deprecated This API would be removed when all of caller has been updated.
+     * */
+    @Deprecated
     public void getLatestTetheringEntitlementValue(int type, boolean showEntitlementUi,
             @NonNull final TetheringEntitlementValueListener listener, @Nullable Handler handler) {
         Preconditions.checkNotNull(listener, "TetheringEntitlementValueListener cannot be null.");
@@ -2733,7 +2789,7 @@
         try {
             String pkgName = mContext.getOpPackageName();
             Log.i(TAG, "getLatestTetheringEntitlementValue:" + pkgName);
-            mService.getLatestTetheringEntitlementValue(type, wrappedListener,
+            mService.getLatestTetheringEntitlementResult(type, wrappedListener,
                     showEntitlementUi, pkgName);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 6728712..fd44fc8 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -212,6 +212,6 @@
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
 
-    void getLatestTetheringEntitlementValue(int type, in ResultReceiver receiver,
+    void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg);
 }
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a17ebcb..eb0fe33 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -143,6 +143,7 @@
             NET_CAPABILITY_NOT_CONGESTED,
             NET_CAPABILITY_NOT_SUSPENDED,
             NET_CAPABILITY_OEM_PAID,
+            NET_CAPABILITY_MCX
     })
     public @interface NetCapability { }
 
@@ -297,8 +298,14 @@
     @SystemApi
     public static final int NET_CAPABILITY_OEM_PAID = 22;
 
+    /**
+     * Indicates this is a network that has the ability to reach a carrier's Mission Critical
+     * servers.
+     */
+    public static final int NET_CAPABILITY_MCX = 23;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_OEM_PAID;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_MCX;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -346,7 +353,8 @@
             (1 << NET_CAPABILITY_IA) |
             (1 << NET_CAPABILITY_IMS) |
             (1 << NET_CAPABILITY_RCS) |
-            (1 << NET_CAPABILITY_XCAP);
+            (1 << NET_CAPABILITY_XCAP) |
+            (1 << NET_CAPABILITY_MCX);
 
     /**
      * Capabilities that force network to be restricted.
@@ -1614,6 +1622,7 @@
             case NET_CAPABILITY_NOT_CONGESTED:  return "NOT_CONGESTED";
             case NET_CAPABILITY_NOT_SUSPENDED:  return "NOT_SUSPENDED";
             case NET_CAPABILITY_OEM_PAID:       return "OEM_PAID";
+            case NET_CAPABILITY_MCX:            return "MCX";
             default:                            return Integer.toString(capability);
         }
     }
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 6fcd6eb..01dd08f 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -16,6 +16,7 @@
 
 package android.net.http;
 
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Bundle;
@@ -252,7 +253,7 @@
      * @return The {@code X509Certificate} used to create this {@code SslCertificate} or
      * {@code null} if no certificate was provided.
      */
-    public X509Certificate getX509Certificate() {
+    public @Nullable X509Certificate getX509Certificate() {
         return mX509Certificate;
     }
 
diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index fbb15ed..5827f9e 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -19,6 +19,8 @@
 import static android.system.OsConstants.SOL_SOCKET;
 import static android.system.OsConstants.SO_BINDTODEVICE;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.net.MacAddress;
@@ -49,7 +51,7 @@
      *
      * <p>Data sent through the socket will go directly to the underlying network, ignoring VPNs.
      */
-    public static void bindSocketToInterface(FileDescriptor socket, String iface)
+    public static void bindSocketToInterface(@NonNull FileDescriptor socket, @NonNull String iface)
             throws ErrnoException {
         // SO_BINDTODEVICE actually takes a string. This works because the first member
         // of struct ifreq is a NULL-terminated interface name.
@@ -75,7 +77,7 @@
     /**
      * Make a socket address that packet socket can send packets to.
      */
-    public static SocketAddress makePacketSocketAddress(int ifIndex, byte[] hwAddr) {
+    public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) {
         return new PacketSocketAddress(ifIndex, hwAddr);
     }
 
@@ -83,45 +85,21 @@
      * Set an option on a socket that takes a time value argument.
      */
     public static void setSocketTimeValueOption(
-            FileDescriptor fd, int level, int option, long millis) throws ErrnoException {
+            @NonNull FileDescriptor fd, int level, int option, long millis) throws ErrnoException {
         Os.setsockoptTimeval(fd, level, option, StructTimeval.fromMillis(millis));
     }
 
     /**
-     * Bind a socket to the specified address.
-     */
-    public static void bindSocket(FileDescriptor fd, SocketAddress addr)
-            throws ErrnoException, SocketException {
-        Os.bind(fd, addr);
-    }
-
-    /**
-     * Connect a socket to the specified address.
-     */
-    public static void connectSocket(FileDescriptor fd, SocketAddress addr)
-            throws ErrnoException, SocketException {
-        Os.connect(fd, addr);
-    }
-
-    /**
-     * Send a message on a socket, using the specified SocketAddress.
-     */
-    public static void sendTo(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount,
-            int flags, SocketAddress addr) throws ErrnoException, SocketException {
-        Os.sendto(fd, bytes, byteOffset, byteCount, flags, addr);
-    }
-
-    /**
      * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor)
      */
-    public static void closeSocket(FileDescriptor fd) throws IOException {
+    public static void closeSocket(@Nullable FileDescriptor fd) throws IOException {
         IoBridge.closeAndSignalBlockedThreads(fd);
     }
 
     /**
      * Attaches a socket filter that accepts DHCP packets to the given socket.
      */
-    public static void attachDhcpFilter(FileDescriptor fd) throws SocketException {
+    public static void attachDhcpFilter(@NonNull FileDescriptor fd) throws SocketException {
         NetworkUtils.attachDhcpFilter(fd);
     }
 
@@ -130,7 +108,8 @@
      * @param fd the socket's {@link FileDescriptor}.
      * @param packetType the hardware address type, one of ARPHRD_*.
      */
-    public static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException {
+    public static void attachRaFilter(@NonNull FileDescriptor fd, int packetType)
+            throws SocketException {
         NetworkUtils.attachRaFilter(fd, packetType);
     }
 
@@ -142,7 +121,7 @@
      * @param fd the socket's {@link FileDescriptor}.
      * @param packetType the hardware address type, one of ARPHRD_*.
      */
-    public static void attachControlPacketFilter(FileDescriptor fd, int packetType)
+    public static void attachControlPacketFilter(@NonNull FileDescriptor fd, int packetType)
             throws SocketException {
         NetworkUtils.attachControlPacketFilter(fd, packetType);
     }
@@ -150,8 +129,8 @@
     /**
      * Add an entry into the ARP cache.
      */
-    public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname,
-            FileDescriptor fd) throws IOException {
+    public static void addArpEntry(@NonNull Inet4Address ipv4Addr, @NonNull MacAddress ethAddr,
+            @NonNull String ifname, @NonNull FileDescriptor fd) throws IOException {
         NetworkUtils.addArpEntry(ipv4Addr, ethAddr, ifname, fd);
     }
 
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 0ec63b5..2c453bf 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 
@@ -241,7 +242,7 @@
      * @param x a {@link NativeHandle} instance to write
      * @throws IndexOutOfBoundsException when [offset, offset + sizeof(jobject)] is out of range
      */
-    public native final void putNativeHandle(long offset, NativeHandle x);
+    public native final void putNativeHandle(long offset, @Nullable NativeHandle x);
 
     /**
      * Put a boolean array contiguously at an offset in the blob.
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 7919a00..dc640c9 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -17,6 +17,8 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 
@@ -123,7 +125,7 @@
      *
      * @param val to write
      */
-    public native final void writeNativeHandle(NativeHandle val);
+    public native final void writeNativeHandle(@Nullable NativeHandle val);
 
     /**
      * Writes an array of boolean values to the end of the parcel.
@@ -170,6 +172,9 @@
     private native final void writeStringVector(String[] val);
     /**
      * Writes an array of native handles to the end of the parcel.
+     *
+     * Individual elements may be null but not the whole array.
+     *
      * @param val array of {@link NativeHandle} objects to write
      */
     private native final void writeNativeHandleVector(NativeHandle[] val);
@@ -284,7 +289,7 @@
      * Helper method to write a list of native handles to the end of the parcel.
      * @param val list of {@link NativeHandle} objects to write
      */
-    public final void writeNativeHandleVector(ArrayList<NativeHandle> val) {
+    public final void writeNativeHandleVector(@NonNull ArrayList<NativeHandle> val) {
         writeNativeHandleVector(val.toArray(new NativeHandle[val.size()]));
     }
 
@@ -359,7 +364,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public native final NativeHandle readNativeHandle();
+    public native final @Nullable NativeHandle readNativeHandle();
     /**
      * Reads an embedded native handle (without duplicating the underlying
      * file descriptors) from the parcel. These file descriptors will only
@@ -372,7 +377,7 @@
      * @return a {@link NativeHandle} instance parsed from the parcel
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public native final NativeHandle readEmbeddedNativeHandle(
+    public native final @Nullable NativeHandle readEmbeddedNativeHandle(
             long parentHandle, long offset);
 
     /**
@@ -521,7 +526,7 @@
      * @return array of {@link NativeHandle} objects.
      * @throws IllegalArgumentException if the parcel has no more data
      */
-    public final ArrayList<NativeHandle> readNativeHandleVector() {
+    public final @NonNull ArrayList<NativeHandle> readNativeHandleVector() {
         return new ArrayList<NativeHandle>(Arrays.asList(readNativeHandleAsArray()));
     }
 
diff --git a/core/java/android/os/IncidentReportArgs.java b/core/java/android/os/IncidentReportArgs.java
index 1bdfd94..a1f2430 100644
--- a/core/java/android/os/IncidentReportArgs.java
+++ b/core/java/android/os/IncidentReportArgs.java
@@ -36,6 +36,8 @@
     private final ArrayList<byte[]> mHeaders = new ArrayList<byte[]>();
     private boolean mAll;
     private int mPrivacyPolicy;
+    private String mReceiverPkg;
+    private String mReceiverCls;
 
     /**
      * Construct an incident report args with no fields.
@@ -73,6 +75,10 @@
         }
 
         out.writeInt(mPrivacyPolicy);
+
+        out.writeString(mReceiverPkg);
+
+        out.writeString(mReceiverCls);
     }
 
     public void readFromParcel(Parcel in) {
@@ -91,6 +97,10 @@
         }
 
         mPrivacyPolicy = in.readInt();
+
+        mReceiverPkg = in.readString();
+
+        mReceiverCls = in.readString();
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<IncidentReportArgs> CREATOR
@@ -126,6 +136,8 @@
         sb.append(mHeaders.size());
         sb.append(" headers), ");
         sb.append("privacy: ").append(mPrivacyPolicy);
+        sb.append("receiver pkg: ").append(mReceiverPkg);
+        sb.append("receiver cls: ").append(mReceiverCls);
         return sb.toString();
     }
 
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
index f13bf5f..8d341b6 100644
--- a/core/java/android/os/NativeHandle.java
+++ b/core/java/android/os/NativeHandle.java
@@ -99,6 +99,8 @@
      * @return a boolean value
      */
     public boolean hasSingleFileDescriptor() {
+        checkOpen();
+
         return mFds.length == 1 && mInts.length == 0;
     }
 
@@ -108,7 +110,7 @@
      * If this method is called, this must also be explicitly closed with
      * {@link #close()}.
      */
-    public NativeHandle dup() throws java.io.IOException {
+    public @NonNull NativeHandle dup() throws java.io.IOException {
         FileDescriptor[] fds = new FileDescriptor[mFds.length];
         try {
             for (int i = 0; i < mFds.length; i++) {
@@ -123,6 +125,12 @@
         return new NativeHandle(fds, mInts, true /*own*/);
     }
 
+    private void checkOpen() {
+        if (mFds == null) {
+            throw new IllegalStateException("NativeHandle is invalidated after close.");
+        }
+    }
+
     /**
      * Closes the file descriptors if they are owned by this object.
      *
@@ -130,19 +138,20 @@
      */
     @Override
     public void close() throws java.io.IOException {
-        if (!mOwn) {
-            return;
-        }
+        checkOpen();
 
-        try {
-            for (FileDescriptor fd : mFds) {
-                Os.close(fd);
+        if (mOwn) {
+            try {
+                for (FileDescriptor fd : mFds) {
+                    Os.close(fd);
+                }
+            } catch (ErrnoException e) {
+                e.rethrowAsIOException();
             }
-        } catch (ErrnoException e) {
-            e.rethrowAsIOException();
+
+            mOwn = false;
         }
 
-        mOwn = false;
         mFds = null;
         mInts = null;
     }
@@ -154,7 +163,9 @@
      * @throws IllegalStateException if this object contains either zero or
      *         more than one file descriptor, or a non-empty data stream.
      */
-    public FileDescriptor getFileDescriptor() {
+    public @NonNull FileDescriptor getFileDescriptor() {
+        checkOpen();
+
         if (!hasSingleFileDescriptor()) {
             throw new IllegalStateException(
                     "NativeHandle is not single file descriptor. Contents must"
@@ -171,6 +182,8 @@
      * @hide
      */
     private int[] getFdsAsIntArray() {
+        checkOpen();
+
         int numFds = mFds.length;
         int[] fds = new int[numFds];
 
@@ -182,11 +195,13 @@
     }
 
     /**
-     * Fetch file descriptors.
+     * Fetch file descriptors
      *
      * @return the fds.
      */
-    public FileDescriptor[] getFileDescriptors() {
+    public @NonNull FileDescriptor[] getFileDescriptors() {
+        checkOpen();
+
         return mFds;
     }
 
@@ -195,7 +210,9 @@
      *
      * @return the opaque data stream.
      */
-    public int[] getInts() {
+    public @NonNull int[] getInts() {
+        checkOpen();
+
         return mInts;
     }
 }
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 82d1b1a..286185b 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.AppIdInt;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
@@ -40,7 +41,7 @@
     /** @hide A user handle to indicate all users on the device */
     @SystemApi
     @TestApi
-    public static final UserHandle ALL = new UserHandle(USER_ALL);
+    public static final @NonNull UserHandle ALL = new UserHandle(USER_ALL);
 
     /** @hide A user id to indicate the currently active user */
     public static final @UserIdInt int USER_CURRENT = -2;
@@ -48,7 +49,7 @@
     /** @hide A user handle to indicate the current user of the device */
     @SystemApi
     @TestApi
-    public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
+    public static final @NonNull UserHandle CURRENT = new UserHandle(USER_CURRENT);
 
     /** @hide A user id to indicate that we would like to send to the current
      *  user, but if this is calling from a user process then we will send it
@@ -58,7 +59,7 @@
     /** @hide A user handle to indicate that we would like to send to the current
      *  user, but if this is calling from a user process then we will send it
      *  to the caller's user instead of failing with a security exception */
-    public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
+    public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
 
     /** @hide An undefined user id */
     public static final @UserIdInt int USER_NULL = -10000;
@@ -77,7 +78,7 @@
      * check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
      */
     @Deprecated
-    public static final UserHandle OWNER = new UserHandle(USER_OWNER);
+    public static final @NonNull UserHandle OWNER = new UserHandle(USER_OWNER);
 
     /** @hide A user id constant to indicate the "system" user of the device */
     public static final @UserIdInt int USER_SYSTEM = 0;
@@ -88,7 +89,7 @@
     /** @hide A user handle to indicate the "system" user of the device */
     @SystemApi
     @TestApi
-    public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
+    public static final @NonNull UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
 
     /**
      * @hide Enable multi-user related side effects. Set this to false if
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7f73dab..4263377 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2705,7 +2705,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public void setUserName(String name) {
+    public void setUserName(@Nullable String name) {
         setUserName(getUserHandle(), name);
     }
 
@@ -2732,7 +2732,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public void setUserIcon(Bitmap icon) {
+    public void setUserIcon(@NonNull Bitmap icon) {
         setUserIcon(getUserHandle(), icon);
     }
 
@@ -2772,7 +2772,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public Bitmap getUserIcon() {
+    public @Nullable Bitmap getUserIcon() {
         return getUserIcon(getUserHandle());
     }
 
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 44add87..c74cbff 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.content.ContentResolver;
@@ -240,6 +241,7 @@
      *
      * @return The desired effect.
      */
+    @NonNull
     public static VibrationEffect createPredefined(@EffectType int effectId) {
         return get(effectId, true);
     }
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index cb2517e..76e911d 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -40,6 +40,7 @@
     void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
     void isApplicationQualifiedForRole(String roleName, String packageName,
             in RemoteCallback callback);
+    void isRoleVisible(String roleName, in RemoteCallback callback);
     void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
             String permission, int grantState, in RemoteCallback callback);
 }
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index 9d58064..5695e42 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -476,6 +476,26 @@
     }
 
     /**
+     * Check whether a role should be visible to user.
+     *
+     * @param roleName name of the role to check for
+     * @param executor Executor on which to invoke the callback
+     * @param callback Callback to receive the result
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+    public void isRoleVisible(@NonNull String roleName,
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+        checkStringNotEmpty(roleName);
+        checkNotNull(executor);
+        checkNotNull(callback);
+
+        mRemoteService.scheduleRequest(new PendingIsRoleVisibleRequest(mRemoteService, roleName,
+                executor, callback));
+    }
+
+    /**
      * A connection to the remote service
      */
     static final class RemoteService extends
@@ -1222,4 +1242,55 @@
             }
         }
     }
+
+    /**
+     * Request for {@link #isRoleVisible}.
+     */
+    private static final class PendingIsRoleVisibleRequest extends
+            AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
+
+        private final @NonNull String mRoleName;
+        private final @NonNull Consumer<Boolean> mCallback;
+
+        private final @NonNull RemoteCallback mRemoteCallback;
+
+        private PendingIsRoleVisibleRequest(@NonNull RemoteService service,
+                @NonNull String roleName, @NonNull @CallbackExecutor Executor executor,
+                @NonNull Consumer<Boolean> callback) {
+            super(service);
+
+            mRoleName = roleName;
+            mCallback = callback;
+
+            mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    boolean visible;
+                    if (result != null) {
+                        visible = result.getBoolean(KEY_RESULT);
+                    } else {
+                        visible = false;
+                    }
+                    callback.accept(visible);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    finish();
+                }
+            }), null);
+        }
+
+        @Override
+        protected void onTimeout(RemoteService remoteService) {
+            mCallback.accept(false);
+        }
+
+        @Override
+        public void run() {
+            try {
+                getService().getServiceInterface().isRoleVisible(mRoleName, mRemoteCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error checking whether role should be visible", e);
+            }
+        }
+    }
 }
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index ee03689..d375c10 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -179,12 +179,21 @@
      * @param roleName name of the role to check for
      * @param packageName package name of the application to check for
      *
-     * @return whether the application is qualified for the role.
+     * @return whether the application is qualified for the role
      */
     public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
             @NonNull String packageName);
 
     /**
+     * Check whether a role should be visible to user.
+     *
+     * @param roleName name of the role to check for
+     *
+     * @return whether the role should be visible to user
+     */
+    public abstract boolean onIsRoleVisible(@NonNull String roleName);
+
+    /**
      * Set the runtime permission state from a device admin.
      *
      * @param callerPackageName The package name of the admin requesting the change
@@ -344,6 +353,18 @@
             }
 
             @Override
+            public void isRoleVisible(String roleName, RemoteCallback callback) {
+                checkStringNotEmpty(roleName);
+                checkNotNull(callback, "callback");
+
+                enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
+
+                mHandler.sendMessage(obtainMessage(
+                        PermissionControllerService::isRoleVisible,
+                        PermissionControllerService.this, roleName, callback));
+            }
+
+            @Override
             public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
                     String packageName, String permission, int grantState,
                     RemoteCallback callback) {
@@ -445,6 +466,13 @@
         callback.sendResult(result);
     }
 
+    private void isRoleVisible(@NonNull String roleName, @NonNull RemoteCallback callback) {
+        boolean visible = onIsRoleVisible(roleName);
+        Bundle result = new Bundle();
+        result.putBoolean(PermissionControllerManager.KEY_RESULT, visible);
+        callback.sendResult(result);
+    }
+
     private void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
             @NonNull String packageName, @NonNull String permission,
             @PermissionGrantState int grantState, @NonNull RemoteCallback callback) {
diff --git a/core/java/android/permission/RuntimePermissionPresentationInfo.java b/core/java/android/permission/RuntimePermissionPresentationInfo.java
index d66789f..4fce14c 100644
--- a/core/java/android/permission/RuntimePermissionPresentationInfo.java
+++ b/core/java/android/permission/RuntimePermissionPresentationInfo.java
@@ -21,6 +21,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 /**
  * This class contains information about how a runtime permission
  * is to be presented in the UI. A single runtime permission
@@ -35,7 +37,7 @@
     private static final int FLAG_GRANTED = 1 << 0;
     private static final int FLAG_STANDARD = 1 << 1;
 
-    private final CharSequence mLabel;
+    private final @NonNull CharSequence mLabel;
     private final int mFlags;
 
     /**
@@ -45,8 +47,10 @@
      * @param granted Whether the permission is granted.
      * @param standard Whether this is a platform-defined permission.
      */
-    public RuntimePermissionPresentationInfo(CharSequence label,
+    public RuntimePermissionPresentationInfo(@NonNull CharSequence label,
             boolean granted, boolean standard) {
+        Preconditions.checkNotNull(label);
+
         mLabel = label;
         int flags = 0;
         if (granted) {
@@ -58,11 +62,6 @@
         mFlags = flags;
     }
 
-    private RuntimePermissionPresentationInfo(Parcel parcel) {
-        mLabel = parcel.readCharSequence();
-        mFlags = parcel.readInt();
-    }
-
     /**
      * @return Whether the permission is granted.
      */
@@ -97,10 +96,14 @@
         parcel.writeInt(mFlags);
     }
 
-    public static final @android.annotation.NonNull Creator<RuntimePermissionPresentationInfo> CREATOR =
+    public static final @NonNull Creator<RuntimePermissionPresentationInfo> CREATOR =
             new Creator<RuntimePermissionPresentationInfo>() {
         public RuntimePermissionPresentationInfo createFromParcel(Parcel source) {
-            return new RuntimePermissionPresentationInfo(source);
+            CharSequence label = source.readCharSequence();
+            int flags = source.readInt();
+
+            return new RuntimePermissionPresentationInfo(label, (flags & FLAG_GRANTED) != 0,
+                    (flags & FLAG_STANDARD) != 0);
         }
 
         public RuntimePermissionPresentationInfo[] newArray(int size) {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 2cd3c48..60c8d36 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -33,10 +33,12 @@
 import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -64,12 +66,14 @@
     public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
 
     /**
-     * Namespace for all Game Driver features.
+     * Namespace for all activity manager related features that are used at the native level.
+     * These features are applied at reboot.
      *
      * @hide
      */
     @SystemApi
-    public static final String NAMESPACE_GAME_DRIVER = "game_driver";
+    public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT =
+            "activity_manager_native_boot";
 
     /**
      * Namespace for autofill feature that provides suggestions across all apps when
@@ -82,6 +86,14 @@
     public static final String NAMESPACE_AUTOFILL = "autofill";
 
     /**
+     * Namespace for all networking connectivity related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_CONNECTIVITY = "connectivity";
+
+    /**
      * Namespace for content capture feature used by on-device machine intelligence
      * to provide suggestions in a privacy-safe manner.
      *
@@ -92,6 +104,14 @@
     public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
 
     /**
+     * Namespace for all Game Driver features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_GAME_DRIVER = "game_driver";
+
+    /**
      * Namespace for all input-related features that are used at the native level.
      * These features are applied at reboot.
      *
@@ -101,6 +121,14 @@
     public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
 
     /**
+     * Namespace for all media native related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
+
+    /**
      * Namespace for all netd related features.
      *
      * @hide
@@ -109,6 +137,15 @@
     public static final String NAMESPACE_NETD_NATIVE = "netd_native";
 
     /**
+     * Namespace for all runtime native boot related features. Boot in this case refers to the
+     * fact that the properties only take affect after rebooting the device.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_RUNTIME_NATIVE_BOOT = "runtime_native_boot";
+
+    /**
      * Namespace for System UI related features.
      *
      * @hide
@@ -117,6 +154,14 @@
     public static final String NAMESPACE_SYSTEMUI = "systemui";
 
     /**
+     * Namespace for TextClassifier related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_TEXTCLASSIFIER = "textclassifier";
+
+    /**
      * Namespace for all runtime related features.
      *
      * @hide
@@ -174,40 +219,6 @@
     }
 
     /**
-     * Namespace for all runtime native boot related features. Boot in this case refers to the
-     * fact that the properties only take affect after rebooting the device.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface RuntimeNativeBoot {
-        String NAMESPACE = "runtime_native_boot";
-    }
-
-    /**
-     * Namespace for all media native related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface MediaNative {
-        /** The flag namespace for media native features. */
-        String NAMESPACE = "media_native";
-    }
-
-    /**
-     * Namespace for all activity manager related features that are used at the native level.
-     * These features are applied at reboot.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface ActivityManagerNativeBoot {
-        String NAMESPACE = "activity_manager_native_boot";
-        String OFFLOAD_QUEUE_ENABLED = "offload_queue_enabled";
-    }
-
-    /**
      * Namespace for attention-based features provided by on-device machine intelligence.
      *
      * @hide
@@ -663,16 +674,18 @@
     private static void handleChange(Uri uri) {
         List<String> pathSegments = uri.getPathSegments();
         // pathSegments(0) is "config"
-        String namespace = pathSegments.get(1);
-        String name = pathSegments.get(2);
-        String value = getProperty(namespace, name);
+        final String namespace = pathSegments.get(1);
+        final String name = pathSegments.get(2);
+        final String value = getProperty(namespace, name);
         synchronized (sLock) {
-            for (OnPropertyChangedListener listener : sListeners.keySet()) {
+            for (final OnPropertyChangedListener listener : sListeners.keySet()) {
                 if (namespace.equals(sListeners.get(listener).first)) {
                     sListeners.get(listener).second.execute(new Runnable() {
                         @Override
                         public void run() {
-                            listener.onPropertyChanged(namespace, name, value);
+                            Map<String, String> propertyMap = new HashMap(1);
+                            propertyMap.put(name, value);
+                            listener.onPropertiesChanged(new Properties(namespace, propertyMap));
                         }
 
                     });
@@ -699,5 +712,147 @@
          * @param value     The new value of the property which has changed.
          */
         void onPropertyChanged(String namespace, String name, String value);
+
+        /**
+         * Called when one or more properties have changed.
+         *
+         * @param properties Contains the complete collection of properties which have changed for a
+         *         single namespace.
+         */
+        default void onPropertiesChanged(@NonNull Properties properties) {
+            // During the transitional period, this method calls the old one to ensure legacy
+            // callers continue to function as expected. Ignore this if you are implementing it for
+            // yourself.
+            String namespace = properties.getNamespace();
+            for (String name : properties.getKeyset()) {
+                onPropertyChanged(namespace, name, properties.getString(name, null));
+            }
+        }
+    }
+
+    /**
+     * A mapping of properties to values, as well as a single namespace which they all belong to.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static class Properties {
+        private final String mNamespace;
+        private final HashMap<String, String> mMap;
+
+        /**
+         * Create a mapping of properties to values and the namespace they belong to.
+         *
+         * @param namespace The namespace these properties belong to.
+         * @param keyValueMap A map between property names and property values.
+         */
+        Properties(@NonNull String namespace, @Nullable Map<String, String> keyValueMap) {
+            Preconditions.checkNotNull(namespace);
+            mNamespace = namespace;
+            mMap = new HashMap();
+            if (keyValueMap != null) {
+                mMap.putAll(keyValueMap);
+            }
+        }
+
+        /**
+         * @return the namespace all properties within this instance belong to.
+         */
+        @NonNull
+        public String getNamespace() {
+            return mNamespace;
+        }
+
+        /**
+         * @return the non-null set of property names.
+         */
+        @NonNull
+        public Set<String> getKeyset() {
+            return mMap.keySet();
+        }
+
+        /**
+         * Look up the String value of a property.
+         *
+         * @param name         The name of the property to look up.
+         * @param defaultValue The value to return if the property has not been defined.
+         * @return the corresponding value, or defaultValue if none exists.
+         */
+        @Nullable
+        public String getString(@NonNull String name, @Nullable String defaultValue) {
+            Preconditions.checkNotNull(name);
+            String value = mMap.get(name);
+            return value != null ? value : defaultValue;
+        }
+
+        /**
+         * Look up the boolean value of a property.
+         *
+         * @param name         The name of the property to look up.
+         * @param defaultValue The value to return if the property has not been defined.
+         * @return the corresponding value, or defaultValue if none exists.
+         */
+        public boolean getBoolean(@NonNull String name, boolean defaultValue) {
+            Preconditions.checkNotNull(name);
+            String value = mMap.get(name);
+            return value != null ? Boolean.parseBoolean(value) : defaultValue;
+        }
+
+        /**
+         * Look up the int value of a property.
+         *
+         * @param name         The name of the property to look up.
+         * @param defaultValue The value to return if the property has not been defined or fails to
+         *                     parse into an int.
+         * @return the corresponding value, or defaultValue if no valid int is available.
+         */
+        public int getInt(@NonNull String name, int defaultValue) {
+            Preconditions.checkNotNull(name);
+            String value = mMap.get(name);
+            try {
+                return Integer.parseInt(value);
+            } catch (NumberFormatException e) {
+                return defaultValue;
+            }
+        }
+
+        /**
+         * Look up the long value of a property.
+         *
+         * @param name         The name of the property to look up.
+         * @param defaultValue The value to return if the property has not been defined. or fails to
+         *                     parse into a long.
+         * @return the corresponding value, or defaultValue if no valid long is available.
+         */
+        public long getLong(@NonNull String name, long defaultValue) {
+            Preconditions.checkNotNull(name);
+            String value = mMap.get(name);
+            try {
+                return Long.parseLong(value);
+            } catch (NumberFormatException e) {
+                return defaultValue;
+            }
+        }
+
+        /**
+         * Look up the int value of a property.
+         *
+         * @param name         The name of the property to look up.
+         * @param defaultValue The value to return if the property has not been defined. or fails to
+         *                     parse into a float.
+         * @return the corresponding value, or defaultValue if no valid float is available.
+         */
+        public float getFloat(@NonNull String name, float defaultValue) {
+            Preconditions.checkNotNull(name);
+            String value = mMap.get(name);
+            try {
+                return Float.parseFloat(value);
+            } catch (NumberFormatException e) {
+                return defaultValue;
+            } catch (NullPointerException e) {
+                return defaultValue;
+            }
+        }
     }
 }
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 49567b2..4632b75 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -1252,7 +1252,8 @@
      * {@hide}
      */
     @SystemApi
-    public static Uri setManageMode(Uri uri) {
+    public static @NonNull Uri setManageMode(@NonNull Uri uri) {
+        Preconditions.checkNotNull(uri, "uri can not be null");
         return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
     }
 
@@ -1262,7 +1263,8 @@
      * {@hide}
      */
     @SystemApi
-    public static boolean isManageMode(Uri uri) {
+    public static boolean isManageMode(@NonNull Uri uri) {
+        Preconditions.checkNotNull(uri, "uri can not be null");
         return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
     }
 
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 9b9e2de..cb794ad 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -487,10 +487,12 @@
      * @see DocumentsContract#EXTRA_LOADING
      */
     @SuppressWarnings("unused")
+    @Nullable
     public Cursor queryRecentDocuments(
-            String rootId, String[] projection, @Nullable Bundle queryArgs,
-            @Nullable CancellationSignal signal)
-            throws FileNotFoundException {
+            @NonNull String rootId, @Nullable String[] projection, @Nullable Bundle queryArgs,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
+        Preconditions.checkNotNull(rootId, "rootId can not be null");
+
         Cursor c = queryRecentDocuments(rootId, projection);
         Bundle extras = new Bundle();
         c.setExtras(extras);
@@ -697,8 +699,9 @@
      * @see DocumentsContract#EXTRA_ERROR
      */
     @SuppressWarnings("unused")
-    public Cursor querySearchDocuments(@NonNull String rootId, @Nullable String[] projection,
-            @NonNull Bundle queryArgs) throws FileNotFoundException {
+    @Nullable
+    public Cursor querySearchDocuments(@NonNull String rootId,
+            @Nullable String[] projection, @NonNull Bundle queryArgs) throws FileNotFoundException {
         Preconditions.checkNotNull(rootId, "rootId can not be null");
         Preconditions.checkNotNull(queryArgs, "queryArgs can not be null");
         return querySearchDocuments(rootId, DocumentsContract.getSearchDocumentsQuery(queryArgs),
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index a34ac70..1486333 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -98,7 +98,7 @@
     /** The authority for the media provider */
     public static final String AUTHORITY = "media";
     /** A content:// style uri to the authority for the media provider */
-    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
+    public static final @NonNull Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     /**
      * Volume name used for content on "internal" storage of device. This
@@ -146,6 +146,8 @@
     public static final String RETRANSLATE_CALL = "update_titles";
 
     /** {@hide} */
+    public static final String GET_VERSION_CALL = "get_version";
+    /** {@hide} */
     public static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
     /** {@hide} */
     public static final String GET_MEDIA_URI_CALL = "get_media_uri";
@@ -3318,21 +3320,41 @@
     public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
 
     /**
-     * Get the media provider's version.
-     * Applications that import data from the media provider into their own caches
-     * can use this to detect that the media provider changed, and reimport data
-     * as needed. No other assumptions should be made about the meaning of the version.
-     * @param context Context to use for performing the query.
-     * @return A version string, or null if the version could not be determined.
+     * Return an opaque version string describing the {@link MediaStore} state.
+     * <p>
+     * Applications that import data from {@link MediaStore} into their own
+     * caches can use this to detect that {@link MediaStore} has undergone
+     * substantial changes, and that data should be rescanned.
+     * <p>
+     * No other assumptions should be made about the meaning of the version.
+     * <p>
+     * This method returns the version for {@link MediaStore#VOLUME_EXTERNAL};
+     * to obtain a version for a different volume, use
+     * {@link #getVersion(Context, String)}.
      */
-    public static String getVersion(Context context) {
-        final Uri uri = AUTHORITY_URI.buildUpon().appendPath("none").appendPath("version").build();
-        try (Cursor c = context.getContentResolver().query(uri, null, null, null, null)) {
-            if (c.moveToFirst()) {
-                return c.getString(0);
-            }
+    public static @NonNull String getVersion(@NonNull Context context) {
+        return getVersion(context, VOLUME_EXTERNAL);
+    }
+
+    /**
+     * Return an opaque version string describing the {@link MediaStore} state.
+     * <p>
+     * Applications that import data from {@link MediaStore} into their own
+     * caches can use this to detect that {@link MediaStore} has undergone
+     * substantial changes, and that data should be rescanned.
+     * <p>
+     * No other assumptions should be made about the meaning of the version.
+     */
+    public static @NonNull String getVersion(@NonNull Context context, @NonNull String volumeName) {
+        final ContentResolver resolver = context.getContentResolver();
+        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
+            final Bundle in = new Bundle();
+            in.putString(Intent.EXTRA_TEXT, volumeName);
+            final Bundle out = client.call(GET_VERSION_CALL, null, in);
+            return out.getString(Intent.EXTRA_TEXT);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
         }
-        return null;
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5a4108a..3a2564a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -308,6 +308,22 @@
             "android.settings.ACCESSIBILITY_SETTINGS";
 
     /**
+     * Activity Action: Show detail settings of a particular accessibility service.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+     * <p>
+     * Input: {@link Intent#EXTRA_COMPONENT_NAME} must specify the accessibility service component
+     * name to be shown.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     **/
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_ACCESSIBILITY_DETAILS_SETTINGS =
+            "android.settings.ACCESSIBILITY_DETAILS_SETTINGS";
+
+    /**
      * Activity Action: Show settings to control access to usage information.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -3305,6 +3321,17 @@
                         ColorDisplayManager.COLOR_MODE_AUTOMATIC);
 
         /**
+         * The user selected peak refresh rate in frames per second.
+         *
+         * If this isn't set, the system falls back to a device specific default.
+         * @hide
+         */
+        public static final String PEAK_REFRESH_RATE = "peak_refresh_rate";
+
+        private static final Validator PEAK_REFRESH_RATE_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(24f, Float.MAX_VALUE);
+
+        /**
          * The amount of time in milliseconds before the device goes to sleep or begins
          * to dream after a period of inactivity.  This value is also known as the
          * user activity timeout period since the screen isn't necessarily turned off
@@ -7990,9 +8017,9 @@
 
         /**
          * Whether or not face unlock always requires user confirmation, meaning {@link
-         * android.hardware.biometrics.BiometricPrompt.Builder#setRequireConfirmation(boolean)}
+         * android.hardware.biometrics.BiometricPrompt.Builder#setConfirmationRequired(boolean)}
          * is always 'true'. This overrides the behavior that apps choose in the
-         * setRequireConfirmation API.
+         * setConfirmationRequired API.
          * @hide
          */
         public static final String FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION =
@@ -9039,6 +9066,8 @@
          */
         public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer";
 
+        private static final Validator APPLY_RAMPING_RINGER_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Setting whether the global gesture for enabling accessibility is enabled.
          * If this gesture is enabled the user will be able to perfrom it to enable
@@ -10657,7 +10686,7 @@
 
         /**
          * Setting to enable the Wi-Fi link probing.
-         * Disabled by default, and setting it to 1 will enable it.
+         * Enabled by default, and setting it to 0 will disable it.
          * The value is boolean (0 or 1).
          * @hide
          */
@@ -11110,8 +11139,9 @@
 
         /**
          * The threshold value for the number of consecutive dns timeout events received to be a
-         * signal of data stall. Set the value to 0 or less than 0 to disable. Note that the value
-         * should be larger than 0 if the DNS data stall detection is enabled.
+         * signal of data stall. The number of consecutive timeouts needs to be {@code >=} this
+         * threshold to be considered a data stall. Set the value to {@code <= 0} to disable. Note
+         * that the value should be {@code > 0} if the DNS data stall detection is enabled.
          *
          * @hide
          */
@@ -11142,9 +11172,12 @@
                 "data_stall_valid_dns_time_threshold";
 
         /**
-         * Which data stall detection signal to use. Possible values are a union of the powers of 2
-         * of DATA_STALL_EVALUATION_TYPE_*.
+         * Which data stall detection signal to use. This is a bitmask constructed by bitwise-or-ing
+         * (i.e. {@code |}) the DATA_STALL_EVALUATION_TYPE_* values.
          *
+         * Type: int
+         * Valid values:
+         *   {@link #DATA_STALL_EVALUATION_TYPE_DNS} : Use dns as a signal.
          * @hide
          */
         @SystemApi
@@ -11152,6 +11185,15 @@
         public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type";
 
         /**
+         * Use dns timeout counts to detect data stall.
+         *
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
+
+        /**
          * Whether to try cellular data recovery when a bad network is reported.
          *
          * @hide
@@ -11426,6 +11468,15 @@
                 "background_activity_starts_enabled";
 
         /**
+         * The packages temporarily whitelisted to be able so start activities from background.
+         * The list of packages is {@code ":"} colon delimited.
+         *
+         * @hide
+         */
+        public static final String BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST =
+                "background_activity_starts_package_names_whitelist";
+
+        /**
          * @hide
          * @see com.android.server.appbinding.AppBindingConstants
          */
@@ -11868,22 +11919,24 @@
          * entity_list_default use ":" as delimiter for values. Ex:
          *
          * <pre>
-         * smart_linkify_enabled                    (boolean)
-         * system_textclassifier_enabled            (boolean)
-         * model_dark_launch_enabled                (boolean)
-         * smart_selection_enabled                  (boolean)
-         * smart_text_share_enabled                 (boolean)
-         * smart_linkify_enabled                    (boolean)
-         * smart_select_animation_enabled           (boolean)
-         * suggest_selection_max_range_length       (int)
-         * classify_text_max_range_length           (int)
-         * generate_links_max_text_length           (int)
-         * generate_links_log_sample_rate           (int)
-         * entity_list_default                      (String[])
-         * entity_list_not_editable                 (String[])
-         * entity_list_editable                     (String[])
-         * lang_id_threshold_override               (float)
-         * template_intent_factory_enabled          (boolean)
+         * smart_linkify_enabled                            (boolean)
+         * system_textclassifier_enabled                    (boolean)
+         * model_dark_launch_enabled                        (boolean)
+         * smart_selection_enabled                          (boolean)
+         * smart_text_share_enabled                         (boolean)
+         * smart_linkify_enabled                            (boolean)
+         * smart_select_animation_enabled                   (boolean)
+         * suggest_selection_max_range_length               (int)
+         * classify_text_max_range_length                   (int)
+         * generate_links_max_text_length                   (int)
+         * generate_links_log_sample_rate                   (int)
+         * entity_list_default                              (String[])
+         * entity_list_not_editable                         (String[])
+         * entity_list_editable                             (String[])
+         * in_app_conversation_action_types_default         (String[])
+         * notification_conversation_action_types_default   (String[])
+         * lang_id_threshold_override                       (float)
+         * template_intent_factory_enabled                  (boolean)
          * </pre>
          *
          * <p>
@@ -13450,6 +13503,7 @@
          * @hide
          */
         public static final String[] SETTINGS_TO_BACKUP = {
+            APPLY_RAMPING_RINGER,
             BUGREPORT_IN_POWER_MENU,
             STAY_ON_WHILE_PLUGGED_IN,
             APP_AUTO_RESTRICTION_ENABLED,
@@ -13490,6 +13544,7 @@
          */
         public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
         static {
+            VALIDATORS.put(APPLY_RAMPING_RINGER, APPLY_RAMPING_RINGER_VALIDATOR);
             VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
             VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR);
             VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR);
@@ -14538,6 +14593,14 @@
          */
         public static final String BATTERY_CHARGING_STATE_UPDATE_DELAY =
                 "battery_charging_state_update_delay";
+
+        /**
+         * A serialized string of params that will be loaded into a text classifier action model.
+         *
+         * @hide
+         */
+        public static final String TEXT_CLASSIFIER_ACTION_MODEL_PARAMS =
+                "text_classifier_action_model_params";
     }
 
     /**
diff --git a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
index 8f6b6ec..8801217 100644
--- a/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
+++ b/core/java/android/security/keystore/recovery/KeyChainProtectionParams.java
@@ -165,7 +165,7 @@
          * @param userSecretType The secret type
          * @return This builder.
          */
-        public Builder setUserSecretType(@UserSecretType int userSecretType) {
+        public @NonNull Builder setUserSecretType(@UserSecretType int userSecretType) {
             mInstance.mUserSecretType = userSecretType;
             return this;
         }
@@ -179,7 +179,7 @@
          * @param lockScreenUiFormat The UI format
          * @return This builder.
          */
-        public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
+        public @NonNull Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
             mInstance.mLockScreenUiFormat = lockScreenUiFormat;
             return this;
         }
@@ -190,7 +190,7 @@
          * @param keyDerivationParams Key derivation parameters
          * @return This builder.
          */
-        public Builder setKeyDerivationParams(@NonNull KeyDerivationParams
+        public @NonNull Builder setKeyDerivationParams(@NonNull KeyDerivationParams
                 keyDerivationParams) {
             mInstance.mKeyDerivationParams = keyDerivationParams;
             return this;
@@ -202,7 +202,7 @@
          * @param secret The secret.
          * @return This builder.
          */
-        public Builder setSecret(@NonNull byte[] secret) {
+        public @NonNull Builder setSecret(@NonNull byte[] secret) {
             mInstance.mSecret = secret;
             return this;
         }
@@ -216,7 +216,7 @@
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        @NonNull public KeyChainProtectionParams build() {
+        public @NonNull KeyChainProtectionParams build() {
             if (mInstance.mUserSecretType == null) {
                 mInstance.mUserSecretType = TYPE_LOCKSCREEN;
             }
@@ -236,7 +236,7 @@
         Arrays.fill(mSecret, (byte) 0);
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<KeyChainProtectionParams> CREATOR =
+    public static final @NonNull Parcelable.Creator<KeyChainProtectionParams> CREATOR =
             new Parcelable.Creator<KeyChainProtectionParams>() {
         public KeyChainProtectionParams createFromParcel(Parcel in) {
             return new KeyChainProtectionParams(in);
diff --git a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
index 18517aa..2f58471 100644
--- a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
@@ -147,7 +147,7 @@
         return mEncryptedRecoveryKeyBlob;
     }
 
-    public static final @android.annotation.NonNull Creator<KeyChainSnapshot> CREATOR =
+    public static final @NonNull Creator<KeyChainSnapshot> CREATOR =
             new Creator<KeyChainSnapshot>() {
         public KeyChainSnapshot createFromParcel(Parcel in) {
             return new KeyChainSnapshot(in);
@@ -171,7 +171,7 @@
          * @param snapshotVersion The snapshot version
          * @return This builder.
          */
-        public Builder setSnapshotVersion(int snapshotVersion) {
+        public @NonNull Builder setSnapshotVersion(int snapshotVersion) {
             mInstance.mSnapshotVersion = snapshotVersion;
             return this;
         }
@@ -182,7 +182,7 @@
          * @param maxAttempts The maximum number of guesses.
          * @return This builder.
          */
-        public Builder setMaxAttempts(int maxAttempts) {
+        public @NonNull Builder setMaxAttempts(int maxAttempts) {
             mInstance.mMaxAttempts = maxAttempts;
             return this;
         }
@@ -193,7 +193,7 @@
          * @param counterId The counter id.
          * @return This builder.
          */
-        public Builder setCounterId(long counterId) {
+        public @NonNull Builder setCounterId(long counterId) {
             mInstance.mCounterId = counterId;
             return this;
         }
@@ -204,7 +204,7 @@
          * @param serverParams The server parameters
          * @return This builder.
          */
-        public Builder setServerParams(byte[] serverParams) {
+        public @NonNull Builder setServerParams(byte[] serverParams) {
             mInstance.mServerParams = serverParams;
             return this;
         }
@@ -218,7 +218,7 @@
          * @throws CertificateException if the given certificate path cannot be encoded properly
          * @return This builder.
          */
-        public Builder setTrustedHardwareCertPath(@NonNull CertPath certPath)
+        public @NonNull Builder setTrustedHardwareCertPath(@NonNull CertPath certPath)
                 throws CertificateException {
             mInstance.mCertPath = RecoveryCertPath.createRecoveryCertPath(certPath);
             return this;
@@ -230,7 +230,7 @@
          * @param keyChainProtectionParams The UI and key derivation parameters
          * @return This builder.
          */
-        public Builder setKeyChainProtectionParams(
+        public @NonNull Builder setKeyChainProtectionParams(
                 @NonNull List<KeyChainProtectionParams> keyChainProtectionParams) {
             mInstance.mKeyChainProtectionParams = keyChainProtectionParams;
             return this;
@@ -242,7 +242,8 @@
          * @param entryRecoveryData List of application keys
          * @return This builder.
          */
-        public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
+        public @NonNull Builder setWrappedApplicationKeys(
+                @NonNull List<WrappedApplicationKey> entryRecoveryData) {
             mInstance.mEntryRecoveryData = entryRecoveryData;
             return this;
         }
@@ -253,7 +254,8 @@
          * @param encryptedRecoveryKeyBlob The recovery key blob.
          * @return This builder.
          */
-        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+        public @NonNull Builder setEncryptedRecoveryKeyBlob(
+                @NonNull byte[] encryptedRecoveryKeyBlob) {
             mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
             return this;
         }
@@ -265,7 +267,7 @@
          * @return new instance
          * @throws NullPointerException if some of the required fields were not set.
          */
-        @NonNull public KeyChainSnapshot build() {
+        public @NonNull KeyChainSnapshot build() {
             Preconditions.checkCollectionElementsNotNull(mInstance.mKeyChainProtectionParams,
                     "keyChainProtectionParams");
             Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
diff --git a/core/java/android/security/keystore/recovery/KeyDerivationParams.java b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
index 6d1533e..d036d14 100644
--- a/core/java/android/security/keystore/recovery/KeyDerivationParams.java
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
@@ -140,7 +140,7 @@
         return mMemoryDifficulty;
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<KeyDerivationParams> CREATOR =
+    public static final @NonNull Parcelable.Creator<KeyDerivationParams> CREATOR =
             new Parcelable.Creator<KeyDerivationParams>() {
         public KeyDerivationParams createFromParcel(Parcel in) {
                 return new KeyDerivationParams(in);
diff --git a/core/java/android/security/keystore/recovery/RecoveryCertPath.java b/core/java/android/security/keystore/recovery/RecoveryCertPath.java
index 04e965f..51bd2ae 100644
--- a/core/java/android/security/keystore/recovery/RecoveryCertPath.java
+++ b/core/java/android/security/keystore/recovery/RecoveryCertPath.java
@@ -74,7 +74,7 @@
         mEncodedCertPath = in.createByteArray();
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<RecoveryCertPath> CREATOR =
+    public static final @NonNull Parcelable.Creator<RecoveryCertPath> CREATOR =
             new Parcelable.Creator<RecoveryCertPath>() {
         public RecoveryCertPath createFromParcel(Parcel in) {
             return new RecoveryCertPath(in);
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index a88aa8c..cc3e578 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -283,6 +283,7 @@
      */
     @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE)
     @NonNull public static RecoveryController getInstance(@NonNull Context context) {
+        // lockSettings may be null.
         ILockSettings lockSettings =
                 ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
         return new RecoveryController(lockSettings, KeyStore.getInstance());
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
index 2b2438a..3e595e0 100644
--- a/core/java/android/security/keystore/recovery/RecoverySession.java
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -193,7 +193,7 @@
      *
      * @hide
      */
-    String getSessionId() {
+    @NonNull String getSessionId() {
         return mSessionId;
     }
 
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
index c6e6272..665c937 100644
--- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -72,7 +72,7 @@
          * @param alias The alias.
          * @return This builder.
          */
-        public Builder setAlias(@NonNull String alias) {
+        public @NonNull Builder setAlias(@NonNull String alias) {
             mInstance.mAlias = alias;
             return this;
         }
@@ -83,7 +83,7 @@
          * @param encryptedKeyMaterial The key material
          * @return This builder
          */
-        public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) {
+        public @NonNull Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) {
             mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial;
             return this;
         }
@@ -94,7 +94,7 @@
          * @param metadata The metadata
          * @return This builder
          */
-        public Builder setMetadata(@Nullable byte[] metadata) {
+        public @NonNull Builder setMetadata(@Nullable byte[] metadata) {
             mInstance.mMetadata = metadata;
             return this;
         }
@@ -105,7 +105,7 @@
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        @NonNull public WrappedApplicationKey build() {
+        public @NonNull WrappedApplicationKey build() {
             Preconditions.checkNotNull(mInstance.mAlias);
             Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
             return mInstance;
@@ -143,7 +143,7 @@
         return mMetadata;
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<WrappedApplicationKey> CREATOR =
+    public static final @NonNull Parcelable.Creator<WrappedApplicationKey> CREATOR =
             new Parcelable.Creator<WrappedApplicationKey>() {
                 public WrappedApplicationKey createFromParcel(Parcel in) {
                     return new WrappedApplicationKey(in);
diff --git a/core/java/android/service/carrier/ApnService.java b/core/java/android/service/carrier/ApnService.java
index d53eb37..57e4b1b 100644
--- a/core/java/android/service/carrier/ApnService.java
+++ b/core/java/android/service/carrier/ApnService.java
@@ -16,6 +16,8 @@
 
 package android.service.carrier;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.WorkerThread;
 import android.app.Service;
@@ -60,7 +62,8 @@
     };
 
     @Override
-    public IBinder onBind(Intent intent) {
+    @NonNull
+    public IBinder onBind(@Nullable Intent intent) {
         return mBinder;
     }
 
@@ -73,5 +76,6 @@
      * subId.
      */
     @WorkerThread
+    @NonNull
     public abstract List<ContentValues> onRestoreApns(int subId);
 }
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index 3a57e3a..3b7392f 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -16,6 +16,7 @@
 
 package android.service.carrier;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -74,7 +75,7 @@
      * @param preciseCarrierId precise carrier identifier
      * {@link TelephonyManager#getSimPreciseCarrierId()}
      */
-    public CarrierIdentifier(String mcc, String mnc, @Nullable String spn,
+    public CarrierIdentifier(@NonNull String mcc, @NonNull String mnc, @Nullable String spn,
                              @Nullable String imsi, @Nullable String gid1, @Nullable String gid2,
                              int carrierid, int preciseCarrierId) {
         mMcc = mcc;
diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
index 40333bf..2814300 100644
--- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
+++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
@@ -52,6 +52,10 @@
 
     /**
      * The action for the intent used to define the content suggestions service.
+     *
+     * <p>To be supported, the service must also require the
+     *      * {@link android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE} permission so
+     *      * that other applications can not abuse it.
      */
     public static final String SERVICE_INTERFACE =
             "android.service.contentsuggestions.ContentSuggestionsService";
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index af0dfd2..1cdb62f 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -32,7 +32,10 @@
  * realizes on the notification rankings.
  *
  * Notifications affected by the Adjustment will be re-ranked if necessary.
+ *
+ * @hide
  */
+@SystemApi
 public final class Adjustment implements Parcelable {
     private final String mPackage;
     private final String mKey;
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 56d22d0..87bdfe0 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.admin.DevicePolicyManager;
@@ -60,7 +61,9 @@
  * <p>
  *     All callbacks are called on the main thread.
  * </p>
+ * @hide
  */
+@SystemApi
 public abstract class NotificationAssistantService extends NotificationListenerService {
     private static final String TAG = "NotificationAssistants";
 
@@ -68,7 +71,14 @@
     @Retention(SOURCE)
     @IntDef({SOURCE_FROM_APP, SOURCE_FROM_ASSISTANT})
     public @interface Source {}
+
+    /**
+     * To indicate an adjustment is from an app.
+     */
     public static final int SOURCE_FROM_APP = 0;
+    /**
+     * To indicate an adjustment is from a {@link NotificationAssistantService}.
+     */
     public static final int SOURCE_FROM_ASSISTANT = 1;
 
     /**
@@ -105,8 +115,8 @@
      * @param sbn the notification to snooze
      * @param snoozeCriterionId the {@link SnoozeCriterion#getId()} representing a device context.
      */
-    abstract public void onNotificationSnoozedUntilContext(StatusBarNotification sbn,
-            String snoozeCriterionId);
+    abstract public void onNotificationSnoozedUntilContext(@NonNull StatusBarNotification sbn,
+            @NonNull String snoozeCriterionId);
 
     /**
      * A notification was posted by an app. Called before post.
@@ -117,7 +127,7 @@
      * @param sbn the new notification
      * @return an adjustment or null to take no action, within 100ms.
      */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn);
+    abstract public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn);
 
     /**
      * A notification was posted by an app. Called before post.
@@ -248,7 +258,7 @@
      * notification.
      * @param key The key of the notification to snooze
      */
-    public final void unsnoozeNotification(String key) {
+    public final void unsnoozeNotification(@NonNull String key) {
         if (!isBound()) return;
         try {
             getNotificationInterface().unsnoozeNotificationFromAssistant(mWrapper, key);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 767a3f7..23607eb 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -425,8 +425,9 @@
      * @hide
      */
     @TestApi
-    public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
-            NotificationStats stats, int reason) {
+    @SystemApi
+    public void onNotificationRemoved(@NonNull StatusBarNotification sbn,
+            @NonNull RankingMap rankingMap, @NonNull NotificationStats stats, int reason) {
         onNotificationRemoved(sbn, rankingMap, reason);
     }
 
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 5a54a43..2b4c24c 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.RemoteInput;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -24,6 +25,12 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+/**
+ * Information about how the user has interacted with a given notification.
+ * @hide
+ */
+@TestApi
+@SystemApi
 public final class NotificationStats implements Parcelable {
 
     private boolean mSeen;
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 74e6c6e..9694998 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.os.Parcel;
@@ -357,7 +358,7 @@
      * Provides a convenient way to set the various fields of a {@link ZenPolicy}.  If a field
      * is not set, it is (@link STATE_UNSET} and will not change the current set policy.
      */
-    public static class Builder {
+    public static final class Builder {
         private ZenPolicy mZenPolicy;
 
         public Builder() {
@@ -378,14 +379,14 @@
         /**
          * Builds the current ZenPolicy.
          */
-        public ZenPolicy build() {
+        public @NonNull ZenPolicy build() {
             return mZenPolicy.copy();
         }
 
         /**
          * Allows all notifications to bypass DND and unmutes all streams.
          */
-        public Builder allowAllSounds() {
+        public @NonNull Builder allowAllSounds() {
             for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
                 mZenPolicy.mPriorityCategories.set(i, STATE_ALLOW);
             }
@@ -401,7 +402,7 @@
          * {@link NotificationChannel#canBypassDnd can bypass DND}. If no channels can bypass DND,
          * the ringer stream is also muted.
          */
-        public Builder disallowAllSounds() {
+        public @NonNull Builder disallowAllSounds() {
             for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
                 mZenPolicy.mPriorityCategories.set(i, STATE_DISALLOW);
             }
@@ -413,7 +414,7 @@
         /**
          * Allows notifications intercepted by DND to show on all surfaces when DND is active.
          */
-        public Builder showAllVisualEffects() {
+        public @NonNull Builder showAllVisualEffects() {
             for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
                 mZenPolicy.mVisualEffects.set(i, STATE_ALLOW);
             }
@@ -423,7 +424,7 @@
         /**
          * Disallows notifications intercepted by DND from showing when DND is active.
          */
-        public Builder hideAllVisualEffects() {
+        public @NonNull Builder hideAllVisualEffects() {
             for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
                 mZenPolicy.mVisualEffects.set(i, STATE_DISALLOW);
             }
@@ -435,7 +436,7 @@
          * unset categories will default to the current applied policy.
          * @hide
          */
-        public Builder unsetPriorityCategory(@PriorityCategory int category) {
+        public @NonNull Builder unsetPriorityCategory(@PriorityCategory int category) {
             mZenPolicy.mPriorityCategories.set(category, STATE_UNSET);
 
             if (category == PRIORITY_CATEGORY_MESSAGES) {
@@ -452,7 +453,7 @@
          * unset effects will default to the current applied policy.
          * @hide
          */
-        public Builder unsetVisualEffect(@VisualEffect int effect) {
+        public @NonNull Builder unsetVisualEffect(@VisualEffect int effect) {
             mZenPolicy.mVisualEffects.set(effect, STATE_UNSET);
             return this;
         }
@@ -461,7 +462,7 @@
          * Whether to allow notifications with category {@link Notification#CATEGORY_REMINDER}
          * to play sounds and visually appear or to intercept them when DND is active.
          */
-        public Builder allowReminders(boolean allow) {
+        public @NonNull Builder allowReminders(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REMINDERS,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -471,7 +472,7 @@
          * Whether to allow notifications with category {@link Notification#CATEGORY_EVENT}
          * to play sounds and visually appear or to intercept them when DND is active.
          */
-        public Builder allowEvents(boolean allow) {
+        public @NonNull Builder allowEvents(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_EVENTS,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -483,7 +484,7 @@
          * them when DND is active.
          * @param audienceType message senders that are allowed to bypass DND
          */
-        public Builder allowMessages(@PeopleType int audienceType) {
+        public @NonNull Builder allowMessages(@PeopleType int audienceType) {
             if (audienceType == STATE_UNSET) {
                 return unsetPriorityCategory(PRIORITY_CATEGORY_MESSAGES);
             }
@@ -507,7 +508,7 @@
          * them when DND is active.
          * @param audienceType callers that are allowed to bypass DND
          */
-        public Builder allowCalls(@PeopleType int audienceType) {
+        public @NonNull  Builder allowCalls(@PeopleType int audienceType) {
             if (audienceType == STATE_UNSET) {
                 return unsetPriorityCategory(PRIORITY_CATEGORY_CALLS);
             }
@@ -530,7 +531,7 @@
          * {@link Notification#CATEGORY_CALL} that have recently called
          * to play sounds and visually appear.
          */
-        public Builder allowRepeatCallers(boolean allow) {
+        public @NonNull Builder allowRepeatCallers(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REPEAT_CALLERS,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -542,7 +543,7 @@
          * to play sounds and visually appear or to intercept them when DND is active.
          * Disallowing alarms will mute the alarm stream when DND is active.
          */
-        public Builder allowAlarms(boolean allow) {
+        public @NonNull Builder allowAlarms(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_ALARMS,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -553,7 +554,7 @@
          * appear or to intercept them when DND is active.
          * Disallowing media will mute the media stream when DND is active.
          */
-        public Builder allowMedia(boolean allow) {
+        public @NonNull Builder allowMedia(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MEDIA,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -563,7 +564,7 @@
          * Whether to allow system sounds to play when DND is active.
          * Disallowing system sounds will mute the system stream when DND is active.
          */
-        public Builder allowSystem(boolean allow) {
+        public @NonNull Builder allowSystem(boolean allow) {
             mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_SYSTEM,
                     allow ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -573,7 +574,7 @@
          * Whether to allow {@link PriorityCategory} sounds to play when DND is active.
          * @hide
          */
-        public Builder allowCategory(@PriorityCategory int category, boolean allow) {
+        public @NonNull Builder allowCategory(@PriorityCategory int category, boolean allow) {
             switch (category) {
                 case PRIORITY_CATEGORY_ALARMS:
                     allowAlarms(allow);
@@ -601,7 +602,7 @@
          * Whether {@link Notification#fullScreenIntent full screen intents} that are intercepted
          * by DND are shown.
          */
-        public Builder showFullScreenIntent(boolean show) {
+        public @NonNull Builder showFullScreenIntent(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_FULL_SCREEN_INTENT,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -611,7 +612,7 @@
          * Whether {@link NotificationChannel#shouldShowLights() notification lights} from
          * notifications intercepted by DND are blocked.
          */
-        public Builder showLights(boolean show) {
+        public @NonNull Builder showLights(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_LIGHTS,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -620,7 +621,7 @@
         /**
          * Whether notifications intercepted by DND are prevented from peeking.
          */
-        public Builder showPeeking(boolean show) {
+        public @NonNull Builder showPeeking(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_PEEK,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -630,7 +631,7 @@
          * Whether notifications intercepted by DND are prevented from appearing in the status bar
          * on devices that support status bars.
          */
-        public Builder showStatusBarIcons(boolean show) {
+        public @NonNull Builder showStatusBarIcons(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_STATUS_BAR,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -640,7 +641,7 @@
          * Whether {@link NotificationChannel#canShowBadge() badges} from
          * notifications intercepted by DND are allowed on devices that support badging.
          */
-        public Builder showBadges(boolean show) {
+        public @NonNull Builder showBadges(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_BADGE,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -650,7 +651,7 @@
          * Whether notification intercepted by DND are prevented from appearing on ambient displays
          * on devices that support ambient display.
          */
-        public Builder showInAmbientDisplay(boolean show) {
+        public @NonNull Builder showInAmbientDisplay(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_AMBIENT,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -661,7 +662,7 @@
          * list views like the notification shade or lockscreen on devices that support those
          * views.
          */
-        public Builder showInNotificationList(boolean show) {
+        public @NonNull Builder showInNotificationList(boolean show) {
             mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_NOTIFICATION_LIST,
                     show ? STATE_ALLOW : STATE_DISALLOW);
             return this;
@@ -672,7 +673,7 @@
          * {@link VisualEffect}
          * @hide
          */
-        public Builder showVisualEffect(@VisualEffect int effect, boolean show) {
+        public @NonNull Builder showVisualEffect(@VisualEffect int effect, boolean show) {
             switch (effect) {
                 case VISUAL_EFFECT_FULL_SCREEN_INTENT:
                     showFullScreenIntent(show);
@@ -1001,7 +1002,7 @@
      * Makes deep copy of this ZenPolicy.
      * @hide
      */
-    public ZenPolicy copy() {
+    public @NonNull ZenPolicy copy() {
         final Parcel parcel = Parcel.obtain();
         try {
             writeToParcel(parcel, 0);
diff --git a/core/java/android/service/textclassifier/IConversationActionsCallback.aidl b/core/java/android/service/textclassifier/IConversationActionsCallback.aidl
deleted file mode 100644
index c35d424..0000000
--- a/core/java/android/service/textclassifier/IConversationActionsCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.textclassifier;
-
-import android.view.textclassifier.ConversationActions;
-
-/**
- * Callback for a ConversationActions request.
- * @hide
- */
-oneway interface IConversationActionsCallback {
-    void onSuccess(in ConversationActions conversationActions);
-    void onFailure();
-}
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/ITextClassificationCallback.aidl b/core/java/android/service/textclassifier/ITextClassificationCallback.aidl
deleted file mode 100644
index 10bfe63..0000000
--- a/core/java/android/service/textclassifier/ITextClassificationCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.textclassifier;
-
-import android.view.textclassifier.TextClassification;
-
-/**
- * Callback for a TextClassification request.
- * @hide
- */
-oneway interface ITextClassificationCallback {
-    void onSuccess(in TextClassification classification);
-    void onFailure();
-}
diff --git a/core/java/android/service/textclassifier/ITextSelectionCallback.aidl b/core/java/android/service/textclassifier/ITextClassifierCallback.aidl
similarity index 82%
rename from core/java/android/service/textclassifier/ITextSelectionCallback.aidl
rename to core/java/android/service/textclassifier/ITextClassifierCallback.aidl
index 1b4c4d1..2926734 100644
--- a/core/java/android/service/textclassifier/ITextSelectionCallback.aidl
+++ b/core/java/android/service/textclassifier/ITextClassifierCallback.aidl
@@ -16,13 +16,14 @@
 
 package android.service.textclassifier;
 
+import android.os.Bundle;
 import android.view.textclassifier.TextSelection;
 
 /**
- * Callback for a TextSelection request.
+ * Callback for all requests from SystemTextClassifier.
  * @hide
  */
-oneway interface ITextSelectionCallback {
-    void onSuccess(in TextSelection selection);
+oneway interface ITextClassifierCallback {
+    void onSuccess(in Bundle result);
     void onFailure();
 }
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/ITextClassifierService.aidl b/core/java/android/service/textclassifier/ITextClassifierService.aidl
index 7941794..2f8d67b 100644
--- a/core/java/android/service/textclassifier/ITextClassifierService.aidl
+++ b/core/java/android/service/textclassifier/ITextClassifierService.aidl
@@ -16,11 +16,7 @@
 
 package android.service.textclassifier;
 
-import android.service.textclassifier.IConversationActionsCallback;
-import android.service.textclassifier.ITextClassificationCallback;
-import android.service.textclassifier.ITextLanguageCallback;
-import android.service.textclassifier.ITextLinksCallback;
-import android.service.textclassifier.ITextSelectionCallback;
+import android.service.textclassifier.ITextClassifierCallback;
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.SelectionEvent;
 import android.view.textclassifier.TextClassification;
@@ -41,17 +37,17 @@
     void onSuggestSelection(
             in TextClassificationSessionId sessionId,
             in TextSelection.Request request,
-            in ITextSelectionCallback callback);
+            in ITextClassifierCallback callback);
 
     void onClassifyText(
             in TextClassificationSessionId sessionId,
             in TextClassification.Request request,
-            in ITextClassificationCallback callback);
+            in ITextClassifierCallback callback);
 
     void onGenerateLinks(
             in TextClassificationSessionId sessionId,
             in TextLinks.Request request,
-            in ITextLinksCallback callback);
+            in ITextClassifierCallback callback);
 
     // TODO: Remove
     void onSelectionEvent(
@@ -72,10 +68,10 @@
     void onDetectLanguage(
             in TextClassificationSessionId sessionId,
             in TextLanguage.Request request,
-            in ITextLanguageCallback callback);
+            in ITextClassifierCallback callback);
 
     void onSuggestConversationActions(
             in TextClassificationSessionId sessionId,
             in ConversationActions.Request request,
-            in IConversationActionsCallback callback);
+            in ITextClassifierCallback callback);
 }
diff --git a/core/java/android/service/textclassifier/ITextLanguageCallback.aidl b/core/java/android/service/textclassifier/ITextLanguageCallback.aidl
deleted file mode 100644
index 263d99af..0000000
--- a/core/java/android/service/textclassifier/ITextLanguageCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.textclassifier;
-
-import android.view.textclassifier.TextLanguage;
-
-/**
- * Callback for a TextLanguage request.
- * @hide
- */
-oneway interface ITextLanguageCallback {
-    void onSuccess(in TextLanguage textLanguage);
-    void onFailure();
-}
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 235b8e8..4088ce8 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -17,6 +17,7 @@
 package android.service.textclassifier;
 
 import android.Manifest;
+import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -27,8 +28,12 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.Slog;
@@ -46,6 +51,10 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.ref.WeakReference;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 /**
  * Abstract base class for the TextClassifier service.
  *
@@ -68,6 +77,11 @@
  *     </intent-filter>
  * </service>}</pre>
  *
+ * <p>From {@link android.os.Build.VERSION_CODES#Q} onward, all callbacks are called on the main
+ * thread. Prior to Q, there is no guarantee on what thread the callback will happen. You should
+ * make sure the callbacks are executed in your desired thread by using a executor, a handler or
+ * something else along the line.
+ *
  * @see TextClassifier
  * @hide
  */
@@ -85,201 +99,102 @@
     public static final String SERVICE_INTERFACE =
             "android.service.textclassifier.TextClassifierService";
 
+    /** @hide **/
+    private static final String KEY_RESULT = "key_result";
+
+    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper(), null, true);
+    private final ExecutorService mSingleThreadExecutor = Executors.newSingleThreadExecutor();
+
     private final ITextClassifierService.Stub mBinder = new ITextClassifierService.Stub() {
 
         // TODO(b/72533911): Implement cancellation signal
         @NonNull private final CancellationSignal mCancellationSignal = new CancellationSignal();
 
-        /** {@inheritDoc} */
         @Override
         public void onSuggestSelection(
                 TextClassificationSessionId sessionId,
-                TextSelection.Request request, ITextSelectionCallback callback) {
+                TextSelection.Request request, ITextClassifierCallback callback) {
             Preconditions.checkNotNull(request);
             Preconditions.checkNotNull(callback);
-            TextClassifierService.this.onSuggestSelection(
-                    sessionId, request, mCancellationSignal,
-                    new Callback<TextSelection>() {
-                        @Override
-                        public void onSuccess(TextSelection result) {
-                            try {
-                                callback.onSuccess(result);
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
+            mMainThreadHandler.post(() -> TextClassifierService.this.onSuggestSelection(
+                    sessionId, request, mCancellationSignal, new ProxyCallback<>(callback)));
 
-                        @Override
-                        public void onFailure(CharSequence error) {
-                            try {
-                                if (callback.asBinder().isBinderAlive()) {
-                                    callback.onFailure();
-                                }
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-                    });
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onClassifyText(
                 TextClassificationSessionId sessionId,
-                TextClassification.Request request, ITextClassificationCallback callback) {
+                TextClassification.Request request, ITextClassifierCallback callback) {
             Preconditions.checkNotNull(request);
             Preconditions.checkNotNull(callback);
-            TextClassifierService.this.onClassifyText(
-                    sessionId, request, mCancellationSignal,
-                    new Callback<TextClassification>() {
-                        @Override
-                        public void onSuccess(TextClassification result) {
-                            try {
-                                callback.onSuccess(result);
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-
-                        @Override
-                        public void onFailure(CharSequence error) {
-                            try {
-                                callback.onFailure();
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-                    });
+            mMainThreadHandler.post(() -> TextClassifierService.this.onClassifyText(
+                    sessionId, request, mCancellationSignal, new ProxyCallback<>(callback)));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onGenerateLinks(
                 TextClassificationSessionId sessionId,
-                TextLinks.Request request, ITextLinksCallback callback) {
+                TextLinks.Request request, ITextClassifierCallback callback) {
             Preconditions.checkNotNull(request);
             Preconditions.checkNotNull(callback);
-            TextClassifierService.this.onGenerateLinks(
-                    sessionId, request,
-                    mCancellationSignal,
-                    new Callback<TextLinks>() {
-                        @Override
-                        public void onSuccess(TextLinks result) {
-                            try {
-                                callback.onSuccess(result);
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-
-                        @Override
-                        public void onFailure(CharSequence error) {
-                            try {
-                                callback.onFailure();
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-                    });
+            mMainThreadHandler.post(() -> TextClassifierService.this.onGenerateLinks(
+                    sessionId, request, mCancellationSignal, new ProxyCallback<>(callback)));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onSelectionEvent(
                 TextClassificationSessionId sessionId,
                 SelectionEvent event) {
             Preconditions.checkNotNull(event);
-            TextClassifierService.this.onSelectionEvent(sessionId, event);
+            mMainThreadHandler.post(
+                    () -> TextClassifierService.this.onSelectionEvent(sessionId, event));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onTextClassifierEvent(
                 TextClassificationSessionId sessionId,
                 TextClassifierEvent event) {
             Preconditions.checkNotNull(event);
-            TextClassifierService.this.onTextClassifierEvent(sessionId, event);
+            mMainThreadHandler.post(
+                    () -> TextClassifierService.this.onTextClassifierEvent(sessionId, event));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onDetectLanguage(
                 TextClassificationSessionId sessionId,
                 TextLanguage.Request request,
-                ITextLanguageCallback callback) {
+                ITextClassifierCallback callback) {
             Preconditions.checkNotNull(request);
             Preconditions.checkNotNull(callback);
-            TextClassifierService.this.onDetectLanguage(
-                    sessionId,
-                    request,
-                    mCancellationSignal,
-                    new Callback<TextLanguage>() {
-                        @Override
-                        public void onSuccess(TextLanguage result) {
-                            try {
-                                callback.onSuccess(result);
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-
-                        @Override
-                        public void onFailure(CharSequence error) {
-                            try {
-                                callback.onFailure();
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        };
-                    });
+            mMainThreadHandler.post(() -> TextClassifierService.this.onDetectLanguage(
+                    sessionId, request, mCancellationSignal, new ProxyCallback<>(callback)));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onSuggestConversationActions(
                 TextClassificationSessionId sessionId,
                 ConversationActions.Request request,
-                IConversationActionsCallback callback) {
+                ITextClassifierCallback callback) {
             Preconditions.checkNotNull(request);
             Preconditions.checkNotNull(callback);
-            TextClassifierService.this.onSuggestConversationActions(
-                    sessionId,
-                    request,
-                    mCancellationSignal,
-                    new Callback<ConversationActions>() {
-                        @Override
-                        public void onSuccess(ConversationActions result) {
-                            try {
-                                callback.onSuccess(result);
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-
-                        @Override
-                        public void onFailure(CharSequence error) {
-                            try {
-                                callback.onFailure();
-                            } catch (RemoteException e) {
-                                Slog.d(LOG_TAG, "Error calling callback");
-                            }
-                        }
-                    });
+            mMainThreadHandler.post(() -> TextClassifierService.this.onSuggestConversationActions(
+                    sessionId, request, mCancellationSignal, new ProxyCallback<>(callback)));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onCreateTextClassificationSession(
                 TextClassificationContext context, TextClassificationSessionId sessionId) {
             Preconditions.checkNotNull(context);
             Preconditions.checkNotNull(sessionId);
-            TextClassifierService.this.onCreateTextClassificationSession(context, sessionId);
+            mMainThreadHandler.post(
+                    () -> TextClassifierService.this.onCreateTextClassificationSession(
+                            context, sessionId));
         }
 
-        /** {@inheritDoc} */
         @Override
         public void onDestroyTextClassificationSession(TextClassificationSessionId sessionId) {
-            TextClassifierService.this.onDestroyTextClassificationSession(sessionId);
+            mMainThreadHandler.post(
+                    () -> TextClassifierService.this.onDestroyTextClassificationSession(sessionId));
         }
     };
 
@@ -301,6 +216,7 @@
      * @param cancellationSignal object to watch for canceling the current operation
      * @param callback the callback to return the result to
      */
+    @MainThread
     public abstract void onSuggestSelection(
             @Nullable TextClassificationSessionId sessionId,
             @NonNull TextSelection.Request request,
@@ -316,6 +232,7 @@
      * @param cancellationSignal object to watch for canceling the current operation
      * @param callback the callback to return the result to
      */
+    @MainThread
     public abstract void onClassifyText(
             @Nullable TextClassificationSessionId sessionId,
             @NonNull TextClassification.Request request,
@@ -331,6 +248,7 @@
      * @param cancellationSignal object to watch for canceling the current operation
      * @param callback the callback to return the result to
      */
+    @MainThread
     public abstract void onGenerateLinks(
             @Nullable TextClassificationSessionId sessionId,
             @NonNull TextLinks.Request request,
@@ -345,12 +263,14 @@
      * @param cancellationSignal object to watch for canceling the current operation
      * @param callback the callback to return the result to
      */
+    @MainThread
     public void onDetectLanguage(
             @Nullable TextClassificationSessionId sessionId,
             @NonNull TextLanguage.Request request,
             @NonNull CancellationSignal cancellationSignal,
             @NonNull Callback<TextLanguage> callback) {
-        callback.onSuccess(getLocalTextClassifier().detectLanguage(request));
+        mSingleThreadExecutor.submit(() ->
+                callback.onSuccess(getLocalTextClassifier().detectLanguage(request)));
     }
 
     /**
@@ -361,12 +281,14 @@
      * @param cancellationSignal object to watch for canceling the current operation
      * @param callback the callback to return the result to
      */
+    @MainThread
     public void onSuggestConversationActions(
             @Nullable TextClassificationSessionId sessionId,
             @NonNull ConversationActions.Request request,
             @NonNull CancellationSignal cancellationSignal,
             @NonNull Callback<ConversationActions> callback) {
-        callback.onSuccess(getLocalTextClassifier().suggestConversationActions(request));
+        mSingleThreadExecutor.submit(() ->
+                callback.onSuccess(getLocalTextClassifier().suggestConversationActions(request)));
     }
 
     /**
@@ -383,6 +305,7 @@
      *      instead
      */
     @Deprecated
+    @MainThread
     public void onSelectionEvent(
             @Nullable TextClassificationSessionId sessionId, @NonNull SelectionEvent event) {}
 
@@ -396,6 +319,7 @@
      * @param sessionId the session id
      * @param event the TextClassifier event
      */
+    @MainThread
     public void onTextClassifierEvent(
             @Nullable TextClassificationSessionId sessionId, @NonNull TextClassifierEvent event) {}
 
@@ -405,6 +329,7 @@
      * @param context the text classification context
      * @param sessionId the session's Id
      */
+    @MainThread
     public void onCreateTextClassificationSession(
             @NonNull TextClassificationContext context,
             @NonNull TextClassificationSessionId sessionId) {}
@@ -414,6 +339,7 @@
      *
      * @param sessionId the id of the session to destroy
      */
+    @MainThread
     public void onDestroyTextClassificationSession(
             @NonNull TextClassificationSessionId sessionId) {}
 
@@ -441,6 +367,11 @@
         return TextClassifier.NO_OP;
     }
 
+    /** @hide **/
+    public static <T extends Parcelable> T getResponse(Bundle bundle) {
+        return bundle.getParcelable(KEY_RESULT);
+    }
+
     /**
      * Callbacks for TextClassifierService results.
      *
@@ -494,4 +425,44 @@
                 si.permission));
         return null;
     }
+
+    /**
+     * Forwards the callback result to a wrapped binder callback.
+     */
+    private static final class ProxyCallback<T extends Parcelable> implements Callback<T> {
+        private WeakReference<ITextClassifierCallback> mTextClassifierCallback;
+
+        private ProxyCallback(ITextClassifierCallback textClassifierCallback) {
+            mTextClassifierCallback =
+                    new WeakReference<>(Preconditions.checkNotNull(textClassifierCallback));
+        }
+
+        @Override
+        public void onSuccess(T result) {
+            ITextClassifierCallback callback = mTextClassifierCallback.get();
+            if (callback == null) {
+                return;
+            }
+            try {
+                Bundle bundle = new Bundle(1);
+                bundle.putParcelable(KEY_RESULT, result);
+                callback.onSuccess(bundle);
+            } catch (RemoteException e) {
+                Slog.d(LOG_TAG, "Error calling callback");
+            }
+        }
+
+        @Override
+        public void onFailure(CharSequence error) {
+            ITextClassifierCallback callback = mTextClassifierCallback.get();
+            if (callback == null) {
+                return;
+            }
+            try {
+                callback.onFailure();
+            } catch (RemoteException e) {
+                Slog.d(LOG_TAG, "Error calling callback");
+            }
+        }
+    }
 }
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index a5d5af2..7fb0f95 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -88,7 +88,7 @@
         /**
          * Constructor called from {@link TextUtils} to restore the span from a parcel
          */
-        public Standard(Parcel src) {
+        public Standard(@NonNull Parcel src) {
             mHeight = src.readInt();
         }
 
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 436cb4f..e2af6f5 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,12 +16,12 @@
 
 package android.util;
 
-import libcore.util.EmptyArray;
-
 import android.annotation.UnsupportedAppUsage;
 
 import com.android.internal.util.ArrayUtils;
 
+import libcore.util.EmptyArray;
+
 import java.util.Collection;
 import java.util.ConcurrentModificationException;
 import java.util.Map;
@@ -453,6 +453,10 @@
      * @return Returns the key stored at the given index.
      */
     public K keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return (K)mArray[index << 1];
     }
 
@@ -462,6 +466,10 @@
      * @return Returns the value stored at the given index.
      */
     public V valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return (V)mArray[(index << 1) + 1];
     }
 
@@ -472,6 +480,10 @@
      * @return Returns the previous value at the given index.
      */
     public V setValueAt(int index, V value) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         index = (index << 1) + 1;
         V old = (V)mArray[index];
         mArray[index] = value;
@@ -665,6 +677,11 @@
      * @return Returns the value that was stored at this index.
      */
     public V removeAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
+
         final Object old = mArray[(index << 1) + 1];
         final int osize = mSize;
         final int nsize;
diff --git a/core/java/android/util/DocumentsStatsLog.java b/core/java/android/util/DocumentsStatsLog.java
index f483944..a67bbde 100644
--- a/core/java/android/util/DocumentsStatsLog.java
+++ b/core/java/android/util/DocumentsStatsLog.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
@@ -126,7 +127,7 @@
      *
      * @param packageName
      */
-    public static void logPickerLaunchedFrom(String packageName) {
+    public static void logPickerLaunchedFrom(@Nullable String packageName) {
         StatsLog.write(StatsLog.DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED, packageName);
     }
 
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index fac699e..b99336b 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -39,6 +39,8 @@
     public static final String SAFETY_HUB = "settings_safety_hub";
     public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
     public static final String GLOBAL_ACTIONS_GRID_ENABLED = "settings_global_actions_grid_enabled";
+    public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
+            "settings_global_actions_panel_enabled";
 
     private static final Map<String, String> DEFAULT_FLAGS;
 
@@ -56,7 +58,8 @@
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
         DEFAULT_FLAGS.put(SAFETY_HUB, "false");
         DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
-        DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "false");
+        DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "true");
+        DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
     }
 
     /**
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index adfa4fc..8b5659b 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.annotation.UnsupportedAppUsage;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.time.LocalDateTime;
@@ -55,6 +56,10 @@
 
     @UnsupportedAppUsage
     public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        dump(pw);
+    }
+
+    public synchronized void dump(PrintWriter pw) {
         Iterator<String> itr = mLog.iterator();
         while (itr.hasNext()) {
             pw.println(itr.next());
@@ -62,6 +67,10 @@
     }
 
     public synchronized void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        reverseDump(pw);
+    }
+
+    public synchronized void reverseDump(PrintWriter pw) {
         Iterator<String> itr = mLog.descendingIterator();
         while (itr.hasNext()) {
             pw.println(itr.next());
@@ -75,10 +84,16 @@
         }
         @UnsupportedAppUsage
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            mLog.dump(fd, pw, args);
+            mLog.dump(pw);
+        }
+        public void dump(PrintWriter pw) {
+            mLog.dump(pw);
         }
         public void reverseDump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            mLog.reverseDump(fd, pw, args);
+            mLog.reverseDump(pw);
+        }
+        public void reverseDump(PrintWriter pw) {
+            mLog.reverseDump(pw);
         }
     }
 
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index 9ba0f5d..e4de704 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -144,6 +144,10 @@
      * Removes the mapping at the specified index.
      */
     public void removeAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mValues[index] != DELETED) {
             mValues[index] = DELETED;
             mGarbage = true;
@@ -233,6 +237,10 @@
      * key.</p>
      */
     public long keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
@@ -253,6 +261,10 @@
      */
     @SuppressWarnings("unchecked")
     public E valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
@@ -266,6 +278,10 @@
      * LongSparseArray stores.
      */
     public void setValueAt(int index, E value) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index af163ac..f167f00 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -171,6 +172,10 @@
      * key.</p>
      */
     public long keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mKeys[index];
     }
 
@@ -186,6 +191,10 @@
      * associated with the largest key.</p>
      */
     public long valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mValues[index];
     }
 
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 89ea2d3..67dfb02 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -171,6 +172,10 @@
      * the behavior is undefined.</p>
      */
     public void removeAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mValues[index] != DELETED) {
             mValues[index] = DELETED;
             mGarbage = true;
@@ -279,6 +284,10 @@
      * the behavior is undefined.</p>
      */
     public int keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
@@ -302,6 +311,10 @@
      */
     @SuppressWarnings("unchecked")
     public E valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
@@ -317,6 +330,10 @@
      * <p>For indices outside of the range <code>0...size()-1</code>, the behavior is undefined.</p>
      */
     public void setValueAt(int index, E value) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         if (mGarbage) {
             gc();
         }
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index d4c4095..03fa1c9 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
 /**
@@ -167,6 +168,10 @@
      * key.</p>
      */
     public int keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mKeys[index];
     }
 
@@ -182,6 +187,10 @@
      * associated with the largest key.</p>
      */
     public boolean valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mValues[index];
     }
 
@@ -189,11 +198,19 @@
      * Directly set the value at a particular index.
      */
     public void setValueAt(int index, boolean value) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         mValues[index] = value;
     }
 
     /** @hide */
     public void setKeyAt(int index, int key) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         mKeys[index] = key;
     }
 
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 9e6bad1..c68dc4e 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -16,14 +16,15 @@
 
 package android.util;
 
+import android.annotation.UnsupportedAppUsage;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 
-import java.util.Arrays;
-
-import android.annotation.UnsupportedAppUsage;
 import libcore.util.EmptyArray;
 
+import java.util.Arrays;
+
 /**
  * SparseIntArrays map integers to integers.  Unlike a normal array of integers,
  * there can be gaps in the indices.  It is intended to be more memory efficient
@@ -171,6 +172,10 @@
      * key.</p>
      */
     public int keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mKeys[index];
     }
 
@@ -186,6 +191,10 @@
      * associated with the largest key.</p>
      */
     public int valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mValues[index];
     }
 
@@ -193,6 +202,10 @@
      * Directly set the value at a particular index.
      */
     public void setValueAt(int index, int value) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         mValues[index] = value;
     }
 
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 81db2b7..37a9202 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -182,6 +182,10 @@
      * key.</p>
      */
     public int keyAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mKeys[index];
     }
 
@@ -197,6 +201,10 @@
      * associated with the largest key.</p>
      */
     public long valueAt(int index) {
+        if (index >= mSize) {
+            // The array might be slightly bigger than mSize, in which case, indexing won't fail.
+            throw new ArrayIndexOutOfBoundsException(index);
+        }
         return mValues[index];
     }
 
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 29ced3e..bf46e95 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -190,6 +190,12 @@
             case PERMISSION_GRANT_REQUEST_RESULT_REPORTED:
                 write(id, (long) params[0], (int) params[1], (String) params[2], (String) params[3],
                         (boolean) params[4], (int) params[5]);
+                break;
+            case DATA_STALL_EVENT:
+                // Refer to the defintion in frameworks/base/cmds/statsd/src/atoms.proto.
+                write(id, (int) params[0], (int) params[1], (int) params[2], (byte[]) params[3],
+                        (byte[]) params[4], (byte[]) params[5]);
+                break;
         }
     }
 
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index ab67d37..71c8e98 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -393,15 +393,18 @@
     /**
      * @return the verity root hash in the Signing Block.
      */
-    public static byte[] getVerityRootHash(String apkPath)
-            throws IOException, SignatureNotFoundException, SecurityException {
+    public static byte[] getVerityRootHash(String apkPath) throws IOException, SecurityException {
         // first try v3
         try {
             return ApkSignatureSchemeV3Verifier.getVerityRootHash(apkPath);
         } catch (SignatureNotFoundException e) {
             // try older version
         }
-        return ApkSignatureSchemeV2Verifier.getVerityRootHash(apkPath);
+        try {
+            return ApkSignatureSchemeV2Verifier.getVerityRootHash(apkPath);
+        } catch (SignatureNotFoundException e) {
+            return null;
+        }
     }
 
     /**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index dbb2071..b3d98b8 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.KeyguardManager;
 import android.content.res.CompatibilityInfo;
@@ -1096,16 +1097,19 @@
      * Returns true if the specified UID has access to this display.
      * @hide
      */
+    @TestApi
     public boolean hasAccess(int uid) {
-        return Display.hasAccess(uid, mFlags, mOwnerUid);
+        return hasAccess(uid, mFlags, mOwnerUid, mDisplayId);
     }
 
     /** @hide */
-    public static boolean hasAccess(int uid, int flags, int ownerUid) {
+    public static boolean hasAccess(int uid, int flags, int ownerUid, int displayId) {
         return (flags & Display.FLAG_PRIVATE) == 0
                 || uid == ownerUid
                 || uid == Process.SYSTEM_UID
-                || uid == 0;
+                || uid == 0
+                // Check if the UID is present on given display.
+                || DisplayManagerGlobal.getInstance().isUidPresentOnDisplay(uid, displayId);
     }
 
     /**
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 11ed357..2efebf6 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -58,6 +58,11 @@
     public int type;
 
     /**
+     * Logical display identifier.
+     */
+    public int displayId;
+
+    /**
      * Display address, or null if none.
      * Interpretation varies by display type.
      */
@@ -305,6 +310,7 @@
                 && layerStack == other.layerStack
                 && flags == other.flags
                 && type == other.type
+                && displayId == other.displayId
                 && Objects.equals(address, other.address)
                 && Objects.equals(uniqueId, other.uniqueId)
                 && appWidth == other.appWidth
@@ -346,6 +352,7 @@
         layerStack = other.layerStack;
         flags = other.flags;
         type = other.type;
+        displayId = other.displayId;
         address = other.address;
         name = other.name;
         uniqueId = other.uniqueId;
@@ -385,6 +392,7 @@
         layerStack = source.readInt();
         flags = source.readInt();
         type = source.readInt();
+        displayId = source.readInt();
         address = source.readParcelable(null);
         name = source.readString();
         appWidth = source.readInt();
@@ -432,6 +440,7 @@
         dest.writeInt(layerStack);
         dest.writeInt(this.flags);
         dest.writeInt(type);
+        dest.writeInt(displayId);
         dest.writeParcelable(address, flags);
         dest.writeString(name);
         dest.writeInt(appWidth);
@@ -579,7 +588,7 @@
      * Returns true if the specified UID has access to this display.
      */
     public boolean hasAccess(int uid) {
-        return Display.hasAccess(uid, flags, ownerUid);
+        return Display.hasAccess(uid, flags, ownerUid, displayId);
     }
 
     private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
@@ -610,6 +619,8 @@
         StringBuilder sb = new StringBuilder();
         sb.append("DisplayInfo{\"");
         sb.append(name);
+        sb.append(", displayId ");
+        sb.append(displayId);
         sb.append("\", uniqueId \"");
         sb.append(uniqueId);
         sb.append("\", app ");
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index f13cb5a..2e27737 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -714,7 +714,8 @@
                 ie.setStackTrace(EMPTY_STACK_TRACE);
                 throw ie;
             } catch (Exception e) {
-                final InflateException ie = new InflateException(parser.getPositionDescription()
+                final InflateException ie = new InflateException(
+                        getParserStateDescription(inflaterContext, attrs)
                         + ": " + e.getMessage(), e);
                 ie.setStackTrace(EMPTY_STACK_TRACE);
                 throw ie;
@@ -730,6 +731,16 @@
         }
     }
 
+    private static String getParserStateDescription(Context context, AttributeSet attrs) {
+        int sourceResId = Resources.getAttributeSetSourceResId(attrs);
+        if (sourceResId == Resources.ID_NULL) {
+            return attrs.getPositionDescription();
+        } else {
+            return attrs.getPositionDescription() + " in "
+                    + context.getResources().getResourceName(sourceResId);
+        }
+    }
+
     private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();
 
     private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
@@ -818,7 +829,7 @@
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
                     if (!allowed) {
-                        failNotAllowed(name, prefix, attrs);
+                        failNotAllowed(name, prefix, viewContext, attrs);
                     }
                 }
                 constructor = clazz.getConstructor(mConstructorSignature);
@@ -837,10 +848,10 @@
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
                         if (!allowed) {
-                            failNotAllowed(name, prefix, attrs);
+                            failNotAllowed(name, prefix, viewContext, attrs);
                         }
                     } else if (allowedState.equals(Boolean.FALSE)) {
-                        failNotAllowed(name, prefix, attrs);
+                        failNotAllowed(name, prefix, viewContext, attrs);
                     }
                 }
             }
@@ -862,14 +873,16 @@
                 mConstructorArgs[0] = lastContext;
             }
         } catch (NoSuchMethodException e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(viewContext, attrs)
                     + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
 
         } catch (ClassCastException e) {
             // If loaded class is not a View subclass
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(viewContext, attrs)
                     + ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -878,7 +891,7 @@
             throw e;
         } catch (Exception e) {
             final InflateException ie = new InflateException(
-                    attrs.getPositionDescription() + ": Error inflating class "
+                    getParserStateDescription(viewContext, attrs) + ": Error inflating class "
                             + (clazz == null ? "<unknown>" : clazz.getName()), e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -890,8 +903,8 @@
     /**
      * Throw an exception because the specified class is not allowed to be inflated.
      */
-    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
-        throw new InflateException(attrs.getPositionDescription()
+    private void failNotAllowed(String name, String prefix, Context context, AttributeSet attrs) {
+        throw new InflateException(getParserStateDescription(context, attrs)
                 + ": Class not allowed to be inflated "+ (prefix != null ? (prefix + name) : name));
     }
 
@@ -1013,13 +1026,15 @@
             throw e;
 
         } catch (ClassNotFoundException e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(context, attrs)
                     + ": Error inflating class " + name, e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
 
         } catch (Exception e) {
-            final InflateException ie = new InflateException(attrs.getPositionDescription()
+            final InflateException ie = new InflateException(
+                    getParserStateDescription(context, attrs)
                     + ": Error inflating class " + name, e);
             ie.setStackTrace(EMPTY_STACK_TRACE);
             throw ie;
@@ -1215,8 +1230,8 @@
                 }
 
                 if (type != XmlPullParser.START_TAG) {
-                    throw new InflateException(childParser.getPositionDescription() +
-                        ": No start tag found!");
+                    throw new InflateException(getParserStateDescription(context, childAttrs)
+                            + ": No start tag found!");
                 }
 
                 final String childName = childParser.getName();
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index f8d5014..b2f3f5e 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -67,6 +67,7 @@
     private boolean mExpanded;
     private boolean mShowExpandButtonAtEnd;
     private boolean mShowWorkBadgeAtEnd;
+    private int mHeaderTextMarginEnd;
     private Drawable mBackground;
     private boolean mEntireHeaderClickable;
     private boolean mExpandOnlyOnButton;
@@ -133,7 +134,8 @@
                 MeasureSpec.AT_MOST);
         int wrapContentHeightSpec = MeasureSpec.makeMeasureSpec(givenHeight,
                 MeasureSpec.AT_MOST);
-        int totalWidth = getPaddingStart() + getPaddingEnd();
+        int totalWidth = getPaddingStart();
+        int iconWidth = getPaddingEnd();
         for (int i = 0; i < getChildCount(); i++) {
             final View child = getChildAt(i);
             if (child.getVisibility() == GONE) {
@@ -146,10 +148,19 @@
             int childHeightSpec = getChildMeasureSpec(wrapContentHeightSpec,
                     lp.topMargin + lp.bottomMargin, lp.height);
             child.measure(childWidthSpec, childHeightSpec);
-            totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            if ((child == mExpandButton && mShowExpandButtonAtEnd)
+                    || child == mProfileBadge
+                    || child == mAppOps) {
+                iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            } else {
+                totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
+            }
         }
-        if (totalWidth > givenWidth) {
-            int overFlow = totalWidth - givenWidth;
+
+        // Ensure that there is at least enough space for the icons
+        int endMargin = Math.max(mHeaderTextMarginEnd, iconWidth);
+        if (totalWidth > givenWidth - endMargin) {
+            int overFlow = totalWidth - givenWidth + endMargin;
             // We are overflowing, lets shrink the app name first
             overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
                     mChildMinWidth);
@@ -161,6 +172,7 @@
             shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
                     0);
         }
+        totalWidth += getPaddingEnd();
         mTotalWidth = Math.min(totalWidth, givenWidth);
         setMeasuredDimension(givenWidth, givenHeight);
     }
@@ -383,6 +395,26 @@
         return mIcon;
     }
 
+    /**
+     * Sets the margin end for the text portion of the header, excluding right-aligned elements
+     * @param headerTextMarginEnd margin size
+     */
+    @RemotableViewMethod
+    public void setHeaderTextMarginEnd(int headerTextMarginEnd) {
+        if (mHeaderTextMarginEnd != headerTextMarginEnd) {
+            mHeaderTextMarginEnd = headerTextMarginEnd;
+            requestLayout();
+        }
+    }
+
+    /**
+     * Get the current margin end value for the header text
+     * @return margin size
+     */
+    public int getHeaderTextMarginEnd() {
+        return mHeaderTextMarginEnd;
+    }
+
     public class HeaderTouchListener implements View.OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 54e70ea..5e2aaae 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -117,6 +117,8 @@
             float dtdy, float dsdy);
     private static native void nativeSetColorTransform(long transactionObj, long nativeObject,
             float[] matrix, float[] translation);
+    private static native void nativeSetColorSpaceAgnostic(long transactionObj, long nativeObject,
+            boolean agnostic);
     private static native void nativeSetGeometry(long transactionObj, long nativeObject,
             Rect sourceCrop, Rect dest, long orientation);
     private static native void nativeSetColor(long transactionObj, long nativeObject, float[] color);
@@ -1207,6 +1209,19 @@
     }
 
     /**
+     * Sets the Surface to be color space agnostic. If a surface is color space agnostic,
+     * the color can be interpreted in any color space.
+     * @param agnostic A boolean to indicate whether the surface is color space agnostic
+     * @hide
+     */
+    public void setColorSpaceAgnostic(boolean agnostic) {
+        checkNotReleased();
+        synchronized (SurfaceControl.class) {
+            sGlobalTransaction.setColorSpaceAgnostic(this, agnostic);
+        }
+    }
+
+    /**
      * Bounds the surface and its children to the bounds specified. Size of the surface will be
      * ignored and only the crop and buffer size will be used to determine the bounds of the
      * surface. If no crop is specified and the surface has no buffer, the surface bounds is only
@@ -2227,6 +2242,18 @@
         }
 
         /**
+         * Sets the Surface to be color space agnostic. If a surface is color space agnostic,
+         * the color can be interpreted in any color space.
+         * @param agnostic A boolean to indicate whether the surface is color space agnostic
+         * @hide
+         */
+        public Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
+            sc.checkNotReleased();
+            nativeSetColorSpaceAgnostic(mNativeObject, sc.mNativeObject, agnostic);
+            return this;
+        }
+
+        /**
          * @hide
          */
         @UnsupportedAppUsage
diff --git a/core/java/android/view/TEST_MAPPING b/core/java/android/view/TEST_MAPPING
new file mode 100644
index 0000000..87d428a
--- /dev/null
+++ b/core/java/android/view/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsUiRenderingTestCases"
+    },
+    {
+      "name": "CtsAccelerationTestCases"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 877b304..287365f7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9530,8 +9530,7 @@
             // View is not important for "regular" autofill, so we must check if Augmented Autofill
             // is enabled for the activity
             final AutofillOptions options = mContext.getAutofillOptions();
-            if (options == null || !options.augmentedEnabled) {
-                // TODO(b/123100824): should also check if activity is whitelisted
+            if (options == null || !options.isAugmentedAutofillEnabled(mContext)) {
                 return false;
             }
             final AutofillManager afm = getAutofillManager();
@@ -18589,7 +18588,7 @@
             @FlagMap(target = FADING_EDGE_VERTICAL, name = "vertical"),
             @FlagMap(target = FADING_EDGE_HORIZONTAL, name = "horizontal")
     })
-    int getFadingEdge() {
+    public int getFadingEdge() {
         return mViewFlags & FADING_EDGE_MASK;
     }
 
@@ -18600,7 +18599,7 @@
      * @hide
      */
     @InspectableProperty
-    int getFadingEdgeLength() {
+    public int getFadingEdgeLength() {
         if (mScrollCache != null && (mViewFlags & FADING_EDGE_MASK) != FADING_EDGE_NONE) {
             return mScrollCache.fadingEdgeLength;
         }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f2474a5..4dc20d4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7845,6 +7845,10 @@
             @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"),
             @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)
+        })
         public int width;
 
         /**
@@ -7856,6 +7860,10 @@
             @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"),
             @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)
+        })
         public int height;
 
         /**
@@ -8028,6 +8036,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_marginLeft")
         public int leftMargin;
 
         /**
@@ -8036,6 +8045,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_marginTop")
         public int topMargin;
 
         /**
@@ -8044,6 +8054,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_marginRight")
         public int rightMargin;
 
         /**
@@ -8052,6 +8063,7 @@
          * to this field.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_marginBottom")
         public int bottomMargin;
 
         /**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 135a891..f3bbca3 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -22,6 +22,7 @@
 import static android.view.WindowInsets.Type.LAST;
 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.TOP_BAR;
 import static android.view.WindowInsets.Type.all;
 import static android.view.WindowInsets.Type.compatSystemInsets;
@@ -35,7 +36,6 @@
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.util.SparseArray;
-import android.view.InsetsState.InternalInsetType;
 import android.view.WindowInsets.Type.InsetType;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethod;
@@ -229,6 +229,7 @@
     static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) {
         typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0);
         typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
+        typeInsetMap[indexOf(SYSTEM_GESTURES)] = Insets.of(insets);
     }
 
     private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
@@ -630,6 +631,28 @@
     }
 
     /**
+     * Returns the system gesture insets.
+     *
+     * <p>The system gesture insets represent the area of a window where 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>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}.
+     *
+     * <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.
+     */
+    @NonNull
+    public Insets getSystemGestureInsets() {
+        return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
+    }
+
+    /**
      * Returns a copy of this WindowInsets with the stable insets fully consumed.
      *
      * @return A modified copy of this WindowInsets
@@ -853,6 +876,22 @@
         }
 
         /**
+         * Sets system gesture insets in pixels.
+         *
+         * <p>The system gesture insets represent the area of a window where 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.
+         *
+         * @see #getSystemGestureInsets()
+         * @return itself
+         */
+        @NonNull
+        public Builder setSystemGestureInsets(@NonNull Insets insets) {
+            WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, 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
@@ -1005,8 +1044,10 @@
         static final int IME = 0x2;
         static final int SIDE_BARS = 0x4;
 
-        static final int LAST = 0x8;
-        static final int SIZE = 4;
+        static final int SYSTEM_GESTURES = 0x8;
+
+        static final int LAST = 0x10;
+        static final int SIZE = 5;
         static final int WINDOW_DECOR = LAST;
 
         static int indexOf(@InsetType int type) {
@@ -1017,8 +1058,10 @@
                     return 1;
                 case SIDE_BARS:
                     return 2;
-                case WINDOW_DECOR:
+                case SYSTEM_GESTURES:
                     return 3;
+                case WINDOW_DECOR:
+                    return 4;
                 default:
                     throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
                             + " type=" + type);
@@ -1030,7 +1073,7 @@
 
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
-        @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR })
+        @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES })
         public @interface InsetType {
         }
 
@@ -1064,6 +1107,27 @@
         }
 
         /**
+         * Returns an inset type representing the system gesture insets.
+         *
+         * <p>The system gesture insets represent the area of a window where 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>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}.
+         *
+         * <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}.
+         *
+         * @see #getSystemGestureInsets()
+         */
+        public static @InsetType int systemGestures() {
+            return SYSTEM_GESTURES;
+        }
+
+        /**
          * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but
          *         not {@link #ime()}.
          */
@@ -1082,6 +1146,9 @@
 
         /**
          * @return All inset types combined.
+         *
+         * TODO: Figure out if this makes sense at all, mixing e.g {@link #systemGestures()} and
+         *       {@link #ime()} does not seem very useful.
          */
         public static @InsetType int all() {
             return 0xFFFFFFFF;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 86b7350..bd38327 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1793,6 +1793,13 @@
         public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 0x00800000;
 
         /**
+         * Flag to indicate that the window is color space agnostic, and the color can be
+         * interpreted to any color space.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC = 0x01000000;
+
+        /**
          * An internal annotation for flags that can be specified to {@link #softInputMode}.
          *
          * @hide
@@ -1892,7 +1899,11 @@
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
                         equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION,
-                        name = "STATUS_FORCE_SHOW_NAVIGATION")
+                        name = "STATUS_FORCE_SHOW_NAVIGATION"),
+                @ViewDebug.FlagToString(
+                        mask = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
+                        equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
+                        name = "COLOR_SPACE_AGNOSTIC")
         })
         @TestApi
         public int privateFlags;
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 5d59e42..df8690d 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -360,7 +360,7 @@
             }
             clearWindowCache();
             final int nodesForWindowCount = mNodeCache.size();
-            for (int i = 0; i < nodesForWindowCount; i++) {
+            for (int i = nodesForWindowCount - 1; i >= 0; i--) {
                 final int windowId = mNodeCache.keyAt(i);
                 clearNodesForWindowLocked(windowId);
             }
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 86f85bf..b9dc0dd 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -24,7 +24,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.LocusId;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -212,11 +211,11 @@
     }
 
     /**
-     * Helper that creates a {@link ContentCaptureContext} associated with the given {@code uri}.
+     * Helper that creates a {@link ContentCaptureContext} associated with the given {@code id}.
      */
     @NonNull
-    public static ContentCaptureContext forLocusId(@NonNull Uri uri) {
-        return new Builder(new LocusId(uri)).build();
+    public static ContentCaptureContext forLocusId(@NonNull String id) {
+        return new Builder(new LocusId(id)).build();
     }
 
     /**
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 885bd2a..a3e6549 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -193,6 +193,15 @@
     private MainContentCaptureSession mMainSession;
 
     /** @hide */
+    public interface ContentCaptureClient {
+        /**
+         * Gets the component name of the client.
+         */
+        @NonNull
+        ComponentName contentCaptureClientGetComponentName();
+    }
+
+    /** @hide */
     public ContentCaptureManager(@NonNull Context context,
             @NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
         mContext = Preconditions.checkNotNull(context, "context cannot be null");
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 6bf1eba..1f0971e 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -121,11 +121,11 @@
     public static final int STATE_INTERNAL_ERROR = 0x100;
 
     /**
-     * Session is disabled because service didn't whitelist package.
+     * Session is disabled because service didn't whitelist package or activity.
      *
      * @hide
      */
-    public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200;
+    public static final int STATE_NOT_WHITELISTED = 0x200;
 
     private static final int INITIAL_CHILDREN_CAPACITY = 5;
 
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
index b273f7c..3e1e4ab 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
@@ -15,6 +15,7 @@
  */
 package android.view.contentcapture;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.app.ActivityThread;
 import android.content.LocusId;
@@ -24,6 +25,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -33,6 +36,19 @@
  */
 public final class UserDataRemovalRequest implements Parcelable {
 
+    /**
+     * When set, service should use the {@link LocusId#getId()} as prefix for the data to be
+     * removed.
+     */
+    public static final int FLAG_IS_PREFIX = 0x1;
+
+    /** @hide */
+    @IntDef(prefix = { "FLAG" }, flag = true, value = {
+            FLAG_IS_PREFIX
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Flags {}
+
     private final String mPackageName;
 
     private final boolean mForEverything;
@@ -46,7 +62,7 @@
             mLocusIdRequests = new ArrayList<>(size);
             for (int i = 0; i < size; i++) {
                 mLocusIdRequests.add(new LocusIdRequest(builder.mLocusIds.get(i),
-                        builder.mRecursive.get(i) == 1));
+                        builder.mFlags.get(i)));
             }
         }
     }
@@ -59,7 +75,7 @@
             mLocusIdRequests = new ArrayList<>(size);
             for (int i = 0; i < size; i++) {
                 mLocusIdRequests.add(new LocusIdRequest((LocusId) parcel.readValue(null),
-                        parcel.readBoolean()));
+                        parcel.readInt()));
             }
         }
     }
@@ -94,7 +110,7 @@
 
         private boolean mForEverything;
         private ArrayList<LocusId> mLocusIds;
-        private IntArray mRecursive;
+        private IntArray mFlags;
 
         private boolean mDestroyed;
 
@@ -116,24 +132,24 @@
          * Request service to remove data associated with a given {@link LocusId}.
          *
          * @param locusId the {@link LocusId} being requested to be removed.
-         * @param recursive whether it should remove the data associated with just the
-         * {@code LocusId} or its tree of descendants.
+         * @param flags either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
          *
          * @return this builder
          */
         @NonNull
-        public Builder addLocusId(@NonNull LocusId locusId, boolean recursive) {
+        public Builder addLocusId(@NonNull LocusId locusId, @Flags int flags) {
             throwIfDestroyed();
             Preconditions.checkState(!mForEverything, "Already is for everything");
             Preconditions.checkNotNull(locusId);
+            // felipeal: check flags
 
             if (mLocusIds == null) {
                 mLocusIds = new ArrayList<>();
-                mRecursive = new IntArray();
+                mFlags = new IntArray();
             }
 
             mLocusIds.add(locusId);
-            mRecursive.add(recursive ? 1 : 0);
+            mFlags.add(flags);
             return this;
         }
 
@@ -144,7 +160,8 @@
         public UserDataRemovalRequest build() {
             throwIfDestroyed();
 
-            Preconditions.checkState(mForEverything || mLocusIds != null);
+            Preconditions.checkState(mForEverything || mLocusIds != null,
+                    "must call either #forEverything() or add one #addLocusId()");
 
             mDestroyed = true;
             return new UserDataRemovalRequest(this);
@@ -170,7 +187,7 @@
             for (int i = 0; i < size; i++) {
                 final LocusIdRequest request = mLocusIdRequests.get(i);
                 parcel.writeValue(request.getLocusId());
-                parcel.writeBoolean(request.isRecursive());
+                parcel.writeInt(request.getFlags());
             }
         }
     }
@@ -196,11 +213,11 @@
      */
     public final class LocusIdRequest {
         private final @NonNull LocusId mLocusId;
-        private final boolean mRecursive;
+        private final @Flags int mFlags;
 
-        private LocusIdRequest(@NonNull LocusId locusId, boolean recursive) {
+        private LocusIdRequest(@NonNull LocusId locusId, @Flags int flags) {
             this.mLocusId = locusId;
-            this.mRecursive = recursive;
+            this.mFlags = flags;
         }
 
         /**
@@ -212,12 +229,13 @@
         }
 
         /**
-         * Checks whether the request is to remove just the data associated with the {@link LocusId}
-         *  per se, or also its descendants.
+         * Gets the flags associates with request.
+         *
+         * @return either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
          */
         @NonNull
-        public boolean isRecursive() {
-            return mRecursive;
+        public @Flags int getFlags() {
+            return mFlags;
         }
     }
 }
diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java
index f859521..97ede86 100644
--- a/core/java/android/view/inspector/InspectableProperty.java
+++ b/core/java/android/view/inspector/InspectableProperty.java
@@ -16,6 +16,7 @@
 
 package android.view.inspector;
 
+import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -39,7 +40,7 @@
  * @see InspectionCompanion#readProperties(Object, PropertyReader)
  * @hide
  */
-@Target({METHOD})
+@Target({METHOD, FIELD})
 @Retention(SOURCE)
 @TestApi
 public @interface InspectableProperty {
@@ -232,6 +233,17 @@
          * @hide
          */
         @TestApi
-        GRAVITY
+        GRAVITY,
+
+        /**
+         * Value is a resource ID
+         *
+         * This type is inferred from the presence of a resource ID annotation such as
+         * {@link android.annotation.AnyRes}.
+         *
+         * @hide
+         */
+        @TestApi
+        RESOURCE_ID
     }
 }
diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java
index 00b18d1..54d99df 100644
--- a/core/java/android/view/inspector/PropertyMapper.java
+++ b/core/java/android/view/inspector/PropertyMapper.java
@@ -157,6 +157,16 @@
             @NonNull IntEnumMapping mapping);
 
     /**
+     * Map a string name to an integer ID for an attribute that contains resource IDs.
+     *
+     * @param name The name of the property
+     * @param attributeId If the property is from an XML attribute, the resource ID of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapResourceId(@NonNull String name, @AttrRes int attributeId);
+
+    /**
      * Map a string name to an integer ID for a flag set packed into an int property.
      *
      * @param name The name of the property
diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java
index a8b7ecc..b5020ce 100644
--- a/core/java/android/view/inspector/PropertyReader.java
+++ b/core/java/android/view/inspector/PropertyReader.java
@@ -16,6 +16,7 @@
 
 package android.view.inspector;
 
+import android.annotation.AnyRes;
 import android.annotation.ColorInt;
 import android.annotation.ColorLong;
 import android.annotation.NonNull;
@@ -150,7 +151,7 @@
     void readColor(int id, @Nullable Color value);
 
     /**
-     * Read {@link android.view.Gravity} packed into an primitive {int}.
+     * Read {@link android.view.Gravity} packed into an primitive {@code int}.
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
@@ -159,7 +160,7 @@
     void readGravity(int id, int value);
 
     /**
-     * Read an enumeration packed into a primitive {int}.
+     * Read an enumeration packed into a primitive {@code int}.
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
@@ -168,7 +169,7 @@
     void readIntEnum(int id, int value);
 
     /**
-     * Read a flag packed into a primitive {int}.
+     * Read a flag packed into a primitive {@code int}.
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
@@ -177,6 +178,15 @@
     void readIntFlag(int id, int value);
 
     /**
+     * Read an integer that contains a resource ID.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a resource ID.
+     */
+    void readResourceId(int id, @AnyRes int value);
+
+    /**
      * Thrown if a client calls a typed read method for a property of a different type.
      */
     class PropertyTypeMismatchException extends RuntimeException {
diff --git a/core/java/android/view/textclassifier/ConfigParser.java b/core/java/android/view/textclassifier/ConfigParser.java
new file mode 100644
index 0000000..8e0bdf9
--- /dev/null
+++ b/core/java/android/view/textclassifier/ConfigParser.java
@@ -0,0 +1,86 @@
+/*
+ * 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.textclassifier;
+
+import android.annotation.Nullable;
+import android.provider.DeviceConfig;
+import android.util.KeyValueListParser;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Retrieves settings from {@link DeviceConfig} and {@link android.provider.Settings}.
+ * It will try DeviceConfig first and then Settings.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public final class ConfigParser {
+    private static final String TAG = "ConfigParser";
+
+    private final KeyValueListParser mParser;
+
+    public ConfigParser(@Nullable String textClassifierConstants) {
+        final KeyValueListParser parser = new KeyValueListParser(',');
+        try {
+            parser.setString(textClassifierConstants);
+        } catch (IllegalArgumentException e) {
+            // Failed to parse the settings string, log this and move on with defaults.
+            Log.w(TAG, "Bad text_classifier_constants: " + textClassifierConstants);
+        }
+        mParser = parser;
+    }
+
+    /**
+     * Reads a boolean flag.
+     */
+    public boolean getBoolean(String key, boolean defaultValue) {
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                key,
+                mParser.getBoolean(key, defaultValue));
+    }
+
+    /**
+     * Reads an integer flag.
+     */
+    public int getInt(String key, int defaultValue) {
+        return DeviceConfig.getInt(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                key,
+                mParser.getInt(key, defaultValue));
+    }
+
+    /**
+     * Reads a float flag.
+     */
+    public float getFloat(String key, float defaultValue) {
+        return DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                key,
+                mParser.getFloat(key, defaultValue));
+    }
+
+    /**
+     * Reads a string flag.
+     */
+    public String getString(String key, String defaultValue) {
+        return DeviceConfig.getString(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                key,
+                mParser.getString(key, defaultValue));
+    }
+}
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 8b370f5..8f8766e 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -20,15 +20,14 @@
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.Looper;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.service.textclassifier.IConversationActionsCallback;
-import android.service.textclassifier.ITextClassificationCallback;
+import android.service.textclassifier.ITextClassifierCallback;
 import android.service.textclassifier.ITextClassifierService;
-import android.service.textclassifier.ITextLanguageCallback;
-import android.service.textclassifier.ITextLinksCallback;
-import android.service.textclassifier.ITextSelectionCallback;
+import android.service.textclassifier.TextClassifierService;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
@@ -73,9 +72,10 @@
         Utils.checkMainThread();
         try {
             request.setCallingPackageName(mPackageName);
-            final TextSelectionCallback callback = new TextSelectionCallback();
+            final BlockingCallback<TextSelection> callback =
+                    new BlockingCallback<>("textselection");
             mManagerService.onSuggestSelection(mSessionId, request, callback);
-            final TextSelection selection = callback.mReceiver.get();
+            final TextSelection selection = callback.get();
             if (selection != null) {
                 return selection;
             }
@@ -95,9 +95,10 @@
         Utils.checkMainThread();
         try {
             request.setCallingPackageName(mPackageName);
-            final TextClassificationCallback callback = new TextClassificationCallback();
+            final BlockingCallback<TextClassification> callback =
+                    new BlockingCallback<>("textclassification");
             mManagerService.onClassifyText(mSessionId, request, callback);
-            final TextClassification classification = callback.mReceiver.get();
+            final TextClassification classification = callback.get();
             if (classification != null) {
                 return classification;
             }
@@ -122,9 +123,10 @@
 
         try {
             request.setCallingPackageName(mPackageName);
-            final TextLinksCallback callback = new TextLinksCallback();
+            final BlockingCallback<TextLinks> callback =
+                    new BlockingCallback<>("textlinks");
             mManagerService.onGenerateLinks(mSessionId, request, callback);
-            final TextLinks links = callback.mReceiver.get();
+            final TextLinks links = callback.get();
             if (links != null) {
                 return links;
             }
@@ -165,9 +167,10 @@
 
         try {
             request.setCallingPackageName(mPackageName);
-            final TextLanguageCallback callback = new TextLanguageCallback();
+            final BlockingCallback<TextLanguage> callback =
+                    new BlockingCallback<>("textlanguage");
             mManagerService.onDetectLanguage(mSessionId, request, callback);
-            final TextLanguage textLanguage = callback.mReceiver.get();
+            final TextLanguage textLanguage = callback.get();
             if (textLanguage != null) {
                 return textLanguage;
             }
@@ -184,9 +187,10 @@
 
         try {
             request.setCallingPackageName(mPackageName);
-            final ConversationActionsCallback callback = new ConversationActionsCallback();
+            final BlockingCallback<ConversationActions> callback =
+                    new BlockingCallback<>("conversation-actions");
             mManagerService.onSuggestConversationActions(mSessionId, request, callback);
-            final ConversationActions conversationActions = callback.mReceiver.get();
+            final ConversationActions conversationActions = callback.get();
             if (conversationActions != null) {
                 return conversationActions;
             }
@@ -245,82 +249,28 @@
         }
     }
 
-    private static final class TextSelectionCallback extends ITextSelectionCallback.Stub {
+    private static final class BlockingCallback<T extends Parcelable>
+            extends ITextClassifierCallback.Stub {
+        private final ResponseReceiver<T> mReceiver;
 
-        final ResponseReceiver<TextSelection> mReceiver = new ResponseReceiver<>("textselection");
+        BlockingCallback(String name) {
+            mReceiver = new ResponseReceiver<>(name);
+        }
 
         @Override
-        public void onSuccess(TextSelection selection) {
-            mReceiver.onSuccess(selection);
+        public void onSuccess(Bundle result) {
+            mReceiver.onSuccess(TextClassifierService.getResponse(result));
         }
 
         @Override
         public void onFailure() {
             mReceiver.onFailure();
         }
-    }
 
-    private static final class TextClassificationCallback extends ITextClassificationCallback.Stub {
-
-        final ResponseReceiver<TextClassification> mReceiver =
-                new ResponseReceiver<>("textclassification");
-
-        @Override
-        public void onSuccess(TextClassification classification) {
-            mReceiver.onSuccess(classification);
+        public T get() {
+            return mReceiver.get();
         }
 
-        @Override
-        public void onFailure() {
-            mReceiver.onFailure();
-        }
-    }
-
-    private static final class TextLinksCallback extends ITextLinksCallback.Stub {
-
-        final ResponseReceiver<TextLinks> mReceiver = new ResponseReceiver<>("textlinks");
-
-        @Override
-        public void onSuccess(TextLinks links) {
-            mReceiver.onSuccess(links);
-        }
-
-        @Override
-        public void onFailure() {
-            mReceiver.onFailure();
-        }
-    }
-
-    private static final class TextLanguageCallback extends ITextLanguageCallback.Stub {
-
-        final ResponseReceiver<TextLanguage> mReceiver = new ResponseReceiver<>("textlanguage");
-
-        @Override
-        public void onSuccess(TextLanguage textLanguage) {
-            mReceiver.onSuccess(textLanguage);
-        }
-
-        @Override
-        public void onFailure() {
-            mReceiver.onFailure();
-        }
-    }
-
-    private static final class ConversationActionsCallback
-            extends IConversationActionsCallback.Stub {
-
-        final ResponseReceiver<ConversationActions> mReceiver =
-                new ResponseReceiver<>("conversationaction");
-
-        @Override
-        public void onSuccess(ConversationActions conversationActions) {
-            mReceiver.onSuccess(conversationActions);
-        }
-
-        @Override
-        public void onFailure() {
-            mReceiver.onFailure();
-        }
     }
 
     private static final class ResponseReceiver<T> {
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 2ef8d04..125b0d3 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -17,8 +17,6 @@
 package android.view.textclassifier;
 
 import android.annotation.Nullable;
-import android.util.KeyValueListParser;
-import android.util.Slog;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -32,22 +30,24 @@
  * This is encoded as a key=value list, separated by commas. Ex:
  *
  * <pre>
- * smart_linkify_enabled                    (boolean)
- * system_textclassifier_enabled            (boolean)
- * model_dark_launch_enabled                (boolean)
- * smart_selection_enabled                  (boolean)
- * smart_text_share_enabled                 (boolean)
- * smart_linkify_enabled                    (boolean)
- * smart_select_animation_enabled           (boolean)
- * suggest_selection_max_range_length       (int)
- * classify_text_max_range_length           (int)
- * generate_links_max_text_length           (int)
- * generate_links_log_sample_rate           (int)
- * entity_list_default                      (String[])
- * entity_list_not_editable                 (String[])
- * entity_list_editable                     (String[])
- * lang_id_threshold_override               (float)
- * template_intent_factory_enabled          (boolean)
+ * smart_linkify_enabled                            (boolean)
+ * system_textclassifier_enabled                    (boolean)
+ * model_dark_launch_enabled                        (boolean)
+ * smart_selection_enabled                          (boolean)
+ * smart_text_share_enabled                         (boolean)
+ * smart_linkify_enabled                            (boolean)
+ * smart_select_animation_enabled                   (boolean)
+ * suggest_selection_max_range_length               (int)
+ * classify_text_max_range_length                   (int)
+ * generate_links_max_text_length                   (int)
+ * generate_links_log_sample_rate                   (int)
+ * entity_list_default                              (String[])
+ * entity_list_not_editable                         (String[])
+ * entity_list_editable                             (String[])
+ * in_app_conversation_action_types_default         (String[])
+ * notification_conversation_action_types_default   (String[])
+ * lang_id_threshold_override                       (float)
+ * template_intent_factory_enabled                  (boolean)
  * </pre>
  *
  * <p>
@@ -61,43 +61,90 @@
  * @hide
  */
 public final class TextClassificationConstants {
-
     private static final String LOG_TAG = "TextClassificationConstants";
 
-    private static final String LOCAL_TEXT_CLASSIFIER_ENABLED =
-            "local_textclassifier_enabled";
-    private static final String SYSTEM_TEXT_CLASSIFIER_ENABLED =
-            "system_textclassifier_enabled";
-    private static final String MODEL_DARK_LAUNCH_ENABLED =
-            "model_dark_launch_enabled";
-    private static final String SMART_SELECTION_ENABLED =
-            "smart_selection_enabled";
-    private static final String SMART_TEXT_SHARE_ENABLED =
-            "smart_text_share_enabled";
-    private static final String SMART_LINKIFY_ENABLED =
-            "smart_linkify_enabled";
+    /**
+     * Whether the smart linkify feature is enabled.
+     */
+    private static final String SMART_LINKIFY_ENABLED = "smart_linkify_enabled";
+    /**
+     * Whether SystemTextClassifier is enabled.
+     */
+    private static final String SYSTEM_TEXT_CLASSIFIER_ENABLED = "system_textclassifier_enabled";
+    /**
+     * Whether TextClassifierImpl is enabled.
+     */
+    private static final String LOCAL_TEXT_CLASSIFIER_ENABLED = "local_textclassifier_enabled";
+    /**
+     * Enable smart selection without a visible UI changes.
+     */
+    private static final String MODEL_DARK_LAUNCH_ENABLED = "model_dark_launch_enabled";
+
+    /**
+     * Whether the smart selection feature is enabled.
+     */
+    private static final String SMART_SELECTION_ENABLED = "smart_selection_enabled";
+    /**
+     * Whether the smart text share feature is enabled.
+     */
+    private static final String SMART_TEXT_SHARE_ENABLED = "smart_text_share_enabled";
+    /**
+     * Whether animation for smart selection is enabled.
+     */
     private static final String SMART_SELECT_ANIMATION_ENABLED =
             "smart_select_animation_enabled";
+    /**
+     * Max length of text that suggestSelection can accept.
+     */
     private static final String SUGGEST_SELECTION_MAX_RANGE_LENGTH =
             "suggest_selection_max_range_length";
-    private static final String CLASSIFY_TEXT_MAX_RANGE_LENGTH =
-            "classify_text_max_range_length";
-    private static final String GENERATE_LINKS_MAX_TEXT_LENGTH =
-            "generate_links_max_text_length";
+    /**
+     * Max length of text that classifyText can accept.
+     */
+    private static final String CLASSIFY_TEXT_MAX_RANGE_LENGTH = "classify_text_max_range_length";
+    /**
+     * Max length of text that generateLinks can accept.
+     */
+    private static final String GENERATE_LINKS_MAX_TEXT_LENGTH = "generate_links_max_text_length";
+    /**
+     * Sampling rate for generateLinks logging.
+     */
     private static final String GENERATE_LINKS_LOG_SAMPLE_RATE =
             "generate_links_log_sample_rate";
-    private static final String ENTITY_LIST_DEFAULT =
-            "entity_list_default";
-    private static final String ENTITY_LIST_NOT_EDITABLE =
-            "entity_list_not_editable";
-    private static final String ENTITY_LIST_EDITABLE =
-            "entity_list_editable";
+    /**
+     * A colon(:) separated string that specifies the default entities types for
+     * generateLinks when hint is not given.
+     */
+    private static final String ENTITY_LIST_DEFAULT = "entity_list_default";
+    /**
+     * A colon(:) separated string that specifies the default entities types for
+     * generateLinks when the text is in a not editable UI widget.
+     */
+    private static final String ENTITY_LIST_NOT_EDITABLE = "entity_list_not_editable";
+    /**
+     * A colon(:) separated string that specifies the default entities types for
+     * generateLinks when the text is in an editable UI widget.
+     */
+    private static final String ENTITY_LIST_EDITABLE = "entity_list_editable";
+    /**
+     * A colon(:) separated string that specifies the default action types for
+     * suggestConversationActions when the suggestions are used in an app.
+     */
     private static final String IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT =
             "in_app_conversation_action_types_default";
+    /**
+     * A colon(:) separated string that specifies the default action types for
+     * suggestConversationActions when the suggestions are used in a notification.
+     */
     private static final String NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT =
             "notification_conversation_action_types_default";
-    private static final String LANG_ID_THRESHOLD_OVERRIDE =
-            "lang_id_threshold_override";
+    /**
+     * Threshold in classifyText to consider a text is in a foreign language.
+     */
+    private static final String LANG_ID_THRESHOLD_OVERRIDE = "lang_id_threshold_override";
+    /**
+     * Whether to enable {@link android.view.textclassifier.TemplateIntentFactory}.
+     */
     private static final String TEMPLATE_INTENT_FACTORY_ENABLED = "template_intent_factory_enabled";
 
     private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
@@ -162,66 +209,77 @@
     private final boolean mTemplateIntentFactoryEnabled;
 
     private TextClassificationConstants(@Nullable String settings) {
-        final KeyValueListParser parser = new KeyValueListParser(',');
-        try {
-            parser.setString(settings);
-        } catch (IllegalArgumentException e) {
-            // Failed to parse the settings string, log this and move on with defaults.
-            Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings);
-        }
-        mSystemTextClassifierEnabled = parser.getBoolean(
-                SYSTEM_TEXT_CLASSIFIER_ENABLED,
-                SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT);
-        mLocalTextClassifierEnabled = parser.getBoolean(
-                LOCAL_TEXT_CLASSIFIER_ENABLED,
-                LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT);
-        mModelDarkLaunchEnabled = parser.getBoolean(
-                MODEL_DARK_LAUNCH_ENABLED,
-                MODEL_DARK_LAUNCH_ENABLED_DEFAULT);
-        mSmartSelectionEnabled = parser.getBoolean(
-                SMART_SELECTION_ENABLED,
-                SMART_SELECTION_ENABLED_DEFAULT);
-        mSmartTextShareEnabled = parser.getBoolean(
-                SMART_TEXT_SHARE_ENABLED,
-                SMART_TEXT_SHARE_ENABLED_DEFAULT);
-        mSmartLinkifyEnabled = parser.getBoolean(
-                SMART_LINKIFY_ENABLED,
-                SMART_LINKIFY_ENABLED_DEFAULT);
-        mSmartSelectionAnimationEnabled = parser.getBoolean(
-                SMART_SELECT_ANIMATION_ENABLED,
-                SMART_SELECT_ANIMATION_ENABLED_DEFAULT);
-        mSuggestSelectionMaxRangeLength = parser.getInt(
-                SUGGEST_SELECTION_MAX_RANGE_LENGTH,
-                SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT);
-        mClassifyTextMaxRangeLength = parser.getInt(
-                CLASSIFY_TEXT_MAX_RANGE_LENGTH,
-                CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT);
-        mGenerateLinksMaxTextLength = parser.getInt(
-                GENERATE_LINKS_MAX_TEXT_LENGTH,
-                GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT);
-        mGenerateLinksLogSampleRate = parser.getInt(
-                GENERATE_LINKS_LOG_SAMPLE_RATE,
-                GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
-        mEntityListDefault = parseStringList(parser.getString(
+        ConfigParser configParser = new ConfigParser(settings);
+        mSystemTextClassifierEnabled =
+                configParser.getBoolean(
+                        SYSTEM_TEXT_CLASSIFIER_ENABLED,
+                        SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT);
+        mLocalTextClassifierEnabled =
+                configParser.getBoolean(
+                        LOCAL_TEXT_CLASSIFIER_ENABLED,
+                        LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT);
+        mModelDarkLaunchEnabled =
+                configParser.getBoolean(
+                        MODEL_DARK_LAUNCH_ENABLED,
+                        MODEL_DARK_LAUNCH_ENABLED_DEFAULT);
+        mSmartSelectionEnabled =
+                configParser.getBoolean(
+                        SMART_SELECTION_ENABLED,
+                        SMART_SELECTION_ENABLED_DEFAULT);
+        mSmartTextShareEnabled =
+                configParser.getBoolean(
+                        SMART_TEXT_SHARE_ENABLED,
+                        SMART_TEXT_SHARE_ENABLED_DEFAULT);
+        mSmartLinkifyEnabled =
+                configParser.getBoolean(
+                        SMART_LINKIFY_ENABLED,
+                        SMART_LINKIFY_ENABLED_DEFAULT);
+        mSmartSelectionAnimationEnabled =
+                configParser.getBoolean(
+                        SMART_SELECT_ANIMATION_ENABLED,
+                        SMART_SELECT_ANIMATION_ENABLED_DEFAULT);
+        mSuggestSelectionMaxRangeLength =
+                configParser.getInt(
+                        SUGGEST_SELECTION_MAX_RANGE_LENGTH,
+                        SUGGEST_SELECTION_MAX_RANGE_LENGTH_DEFAULT);
+        mClassifyTextMaxRangeLength =
+                configParser.getInt(
+                        CLASSIFY_TEXT_MAX_RANGE_LENGTH,
+                        CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT);
+        mGenerateLinksMaxTextLength =
+                configParser.getInt(
+                        GENERATE_LINKS_MAX_TEXT_LENGTH,
+                        GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT);
+        mGenerateLinksLogSampleRate =
+                configParser.getInt(
+                        GENERATE_LINKS_LOG_SAMPLE_RATE,
+                        GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
+        mEntityListDefault = parseStringList(configParser.getString(
                 ENTITY_LIST_DEFAULT,
                 ENTITY_LIST_DEFAULT_VALUE));
-        mEntityListNotEditable = parseStringList(parser.getString(
-                ENTITY_LIST_NOT_EDITABLE,
-                ENTITY_LIST_DEFAULT_VALUE));
-        mEntityListEditable = parseStringList(parser.getString(
-                ENTITY_LIST_EDITABLE,
-                ENTITY_LIST_DEFAULT_VALUE));
-        mInAppConversationActionTypesDefault = parseStringList(parser.getString(
-                IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
-                CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
-        mNotificationConversationActionTypesDefault = parseStringList(parser.getString(
-                NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
-                CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
-        mLangIdThresholdOverride = parser.getFloat(
-                LANG_ID_THRESHOLD_OVERRIDE,
-                LANG_ID_THRESHOLD_OVERRIDE_DEFAULT);
-        mTemplateIntentFactoryEnabled = parser.getBoolean(
-                TEMPLATE_INTENT_FACTORY_ENABLED, TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
+        mEntityListNotEditable = parseStringList(
+                configParser.getString(
+                        ENTITY_LIST_NOT_EDITABLE,
+                        ENTITY_LIST_DEFAULT_VALUE));
+        mEntityListEditable = parseStringList(
+                configParser.getString(
+                        ENTITY_LIST_EDITABLE,
+                        ENTITY_LIST_DEFAULT_VALUE));
+        mInAppConversationActionTypesDefault = parseStringList(
+                configParser.getString(
+                        IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
+                        CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
+        mNotificationConversationActionTypesDefault = parseStringList(
+                configParser.getString(
+                        NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
+                        CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
+        mLangIdThresholdOverride =
+                configParser.getFloat(
+                        LANG_ID_THRESHOLD_OVERRIDE,
+                        LANG_ID_THRESHOLD_OVERRIDE_DEFAULT);
+        mTemplateIntentFactoryEnabled = configParser.getBoolean(
+                TEMPLATE_INTENT_FACTORY_ENABLED,
+                TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT);
     }
 
     /** Load from a settings string. */
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index d047c55..868cbb1 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -20,9 +20,11 @@
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.ServiceManager;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.service.textclassifier.TextClassifierService;
 import android.view.textclassifier.TextClassifier.TextClassifierType;
@@ -195,6 +197,7 @@
             if (mSettingsObserver != null) {
                 getApplicationContext().getContentResolver()
                         .unregisterContentObserver(mSettingsObserver);
+                DeviceConfig.removeOnPropertyChangedListener(mSettingsObserver);
             }
         } finally {
             super.finalize();
@@ -277,7 +280,8 @@
         }
     }
 
-    private static final class SettingsObserver extends ContentObserver {
+    private static final class SettingsObserver extends ContentObserver
+            implements DeviceConfig.OnPropertyChangedListener {
 
         private final WeakReference<TextClassificationManager> mTcm;
 
@@ -288,10 +292,23 @@
                     Settings.Global.getUriFor(Settings.Global.TEXT_CLASSIFIER_CONSTANTS),
                     false /* notifyForDescendants */,
                     this);
+            DeviceConfig.addOnPropertyChangedListener(
+                    DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                    ActivityThread.currentApplication().getMainExecutor(),
+                    this);
         }
 
         @Override
         public void onChange(boolean selfChange) {
+            invalidateSettings();
+        }
+
+        @Override
+        public void onPropertyChanged(String namespace, String name, String value) {
+            invalidateSettings();
+        }
+
+        private void invalidateSettings() {
             final TextClassificationManager tcm = mTcm.get();
             if (tcm != null) {
                 tcm.invalidate();
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index ef69b63..3d3d941 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -79,7 +79,10 @@
     /**
      * Returns {@code true} if the draw GL functor can be invoked (see {@link #invokeDrawGlFunctor})
      * and {@code false} otherwise.
+     *
+     * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)}
      */
+    @Deprecated
     public boolean canInvokeDrawGlFunctor(View containerView) {
         return true;
     }
@@ -90,7 +93,9 @@
      *
      * @param nativeDrawGLFunctor the pointer to the native functor that implements
      *        system/core/include/utils/Functor.h
+     * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)}
      */
+    @Deprecated
     public void invokeDrawGlFunctor(View containerView, long nativeDrawGLFunctor,
             boolean waitForCompletion) {
         ViewRootImpl.invokeFunctor(nativeDrawGLFunctor, waitForCompletion);
@@ -105,7 +110,9 @@
      * @param nativeDrawGLFunctor the pointer to the native functor that implements
      *        system/core/include/utils/Functor.h
      * @throws IllegalArgumentException if the canvas is not hardware accelerated
+     * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)}
      */
+    @Deprecated
     public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
         if (!(canvas instanceof RecordingCanvas)) {
             // Canvas#isHardwareAccelerated() is only true for subclasses of HardwareCanvas.
@@ -126,7 +133,9 @@
      * @param releasedRunnable Called when this nativeDrawGLFunctor is no longer referenced by this
      *        canvas, so is safe to be destroyed.
      * @throws IllegalArgumentException if the canvas is not hardware accelerated
+     * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)}
      */
+    @Deprecated
     public void callDrawGlFunction(@NonNull Canvas canvas, long nativeDrawGLFunctor,
             @Nullable Runnable releasedRunnable) {
         if (!(canvas instanceof RecordingCanvas)) {
@@ -139,7 +148,7 @@
 
     /**
      * Call webview draw functor. See API in draw_fn.h.
-     * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}).
+     * @param canvas a {@link RecordingCanvas}.
      * @param functor created by AwDrawFn_CreateFunctor in draw_fn.h.
      */
     public void drawWebViewFunctor(@NonNull Canvas canvas, int functor) {
@@ -156,7 +165,9 @@
      *
      * @param nativeDrawGLFunctor the pointer to the native functor that implements
      *        system/core/include/utils/Functor.h
+     * @deprecated Use {@link #drawWebViewFunctor(Canvas, int)}
      */
+    @Deprecated
     public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) {
         ViewRootImpl viewRootImpl = containerView.getViewRootImpl();
         if (nativeDrawGLFunctor != 0 && viewRootImpl != null) {
diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java
index 4ce0d5d..e3499f9 100644
--- a/core/java/android/widget/AbsoluteLayout.java
+++ b/core/java/android/widget/AbsoluteLayout.java
@@ -21,6 +21,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.inspector.InspectableProperty;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -159,10 +160,12 @@
         /**
          * The horizontal, or X, location of the child within the view group.
          */
+        @InspectableProperty(name = "layout_x")
         public int x;
         /**
          * The vertical, or Y, location of the child within the view group.
          */
+        @InspectableProperty(name = "layout_y")
         public int y;
 
         /**
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 3570c79..69da911 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -443,6 +443,9 @@
          * @see android.view.Gravity
          * @attr ref android.R.styleable#FrameLayout_Layout_layout_gravity
          */
+        @InspectableProperty(
+                name = "layout_gravity",
+                valueType = InspectableProperty.ValueType.GRAVITY)
         public int gravity = UNSPECIFIED_GRAVITY;
 
         public LayoutParams(@NonNull Context c, @Nullable AttributeSet attrs) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index e833df9..bdde435 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1987,6 +1987,7 @@
          * will be pro-rated among all views whose weight is greater than 0.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_weight")
         public float weight;
 
         /**
@@ -2010,6 +2011,9 @@
             @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
             @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
         })
+        @InspectableProperty(
+                name = "layout_gravity",
+                valueType = InspectableProperty.ValueType.GRAVITY)
         public int gravity = -1;
 
         /**
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index b7cdad2..50e8836 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -1116,7 +1116,7 @@
     /**
      * Builder class for {@link Magnifier} objects.
      */
-    public static class Builder {
+    public static final class Builder {
         private @NonNull View mView;
         private @Px @IntRange(from = 0) int mWidth;
         private @Px @IntRange(from = 0) int mHeight;
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 109c0a4..8ee31e2 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1286,6 +1286,7 @@
          * the anchor's visibility is GONE.
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_alignWithParentIfMissing")
         public boolean alignWithParent;
 
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 457be34..a3e89c8 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1474,7 +1474,7 @@
      *
      * @param child the View to scroll to
      */
-    public void scrollToDescendant(View child) {
+    public void scrollToDescendant(@NonNull View child) {
         if (!mIsLayoutDirty) {
             child.getDrawingRect(mTempRect);
 
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 22931fc..ac23093 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -26,6 +26,7 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
+import android.view.inspector.InspectableProperty;
 
 /**
  * <p>A layout that arranges its children horizontally. A TableRow should
@@ -398,12 +399,14 @@
          * <p>The column index of the cell represented by the widget.</p>
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_column")
         public int column;
 
         /**
          * <p>The number of columns the widgets spans over.</p>
          */
         @ViewDebug.ExportedProperty(category = "layout")
+        @InspectableProperty(name = "layout_span")
         public int span;
 
         private static final int LOCATION = 0;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 73792b0..04bcb14 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12744,7 +12744,7 @@
      * return value may not be the same as the one TextView uses if the View's layout direction is
      * not resolved or detached from parent root view.
      */
-    public TextDirectionHeuristic getTextDirectionHeuristic() {
+    public @NonNull TextDirectionHeuristic getTextDirectionHeuristic() {
         if (hasPasswordTransformationMethod()) {
             // passwords fields should be LTR
             return TextDirectionHeuristics.LTR;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a5a1dd9..fd978f5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -18,6 +18,11 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -90,6 +95,8 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.AbsListView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
@@ -135,7 +142,7 @@
      * {@link AppPredictionManager} will be queried for direct share targets.
      */
     // TODO(b/123089490): Replace with system flag
-    private static final boolean USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS = true;
+    private static final boolean USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS = false;
     // TODO(b/123088566) Share these in a better way.
     private static final String APP_PREDICTION_SHARE_UI_SURFACE = "share";
     public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
@@ -152,11 +159,17 @@
     private static final boolean USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS = true;
     private static final boolean USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS = true;
 
+    /**
+     * The transition time between placeholders for direct share to a message
+     * indicating that non are available.
+     */
+    private static final int NO_DIRECT_SHARE_ANIM_IN_MILLIS = 200;
+
     // TODO(b/121287224): Re-evaluate this limit
     private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
 
     private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
-    private static final int WATCHDOG_TIMEOUT_MILLIS = 2000;
+    private static final int WATCHDOG_TIMEOUT_MILLIS = 3000;
 
     private Bundle mReplacementExtras;
     private IntentSender mChosenComponentSender;
@@ -172,6 +185,8 @@
 
     private ChooserListAdapter mChooserListAdapter;
     private ChooserRowAdapter mChooserRowAdapter;
+    private Drawable mChooserRowLayer;
+    private int mChooserRowServiceSpacing;
 
     private SharedPreferences mPinnedSharedPrefs;
     private static final float PINNED_TARGET_SCORE_BOOST = 1000.f;
@@ -220,7 +235,6 @@
                     sri.connection.destroy();
                     mServiceConnections.remove(sri.connection);
                     if (mServiceConnections.isEmpty()) {
-                        mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
                         sendVoiceChoicesIfNeeded();
                         mChooserListAdapter.setShowServiceTargets(true);
                     }
@@ -230,8 +244,12 @@
                     if (DEBUG) {
                         Log.d(TAG, "CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT; unbinding services");
                     }
+                    if (isDestroyed()) {
+                        break;
+                    }
                     unbindRemainingServices();
                     sendVoiceChoicesIfNeeded();
+                    mChooserListAdapter.completeServiceTargetLoading();
                     mChooserListAdapter.setShowServiceTargets(true);
                     break;
 
@@ -399,11 +417,17 @@
                     .setExtras(extras)
                     .build());
             mAppPredictorCallback = resultList -> {
+                if (isFinishing() || isDestroyed()) {
+                    return;
+                }
                 final List<DisplayResolveInfo> driList =
                         getDisplayResolveInfos(mChooserListAdapter);
                 final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
                         new ArrayList<>();
                 for (AppTarget appTarget : resultList) {
+                    if (appTarget.getShortcutInfo() == null) {
+                        continue;
+                    }
                     shareShortcutInfos.add(new ShortcutManager.ShareShortcutInfo(
                             appTarget.getShortcutInfo(),
                             new ComponentName(
@@ -414,6 +438,10 @@
             mAppPredictor.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
         }
 
+        mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null);
+        mChooserRowServiceSpacing = getResources()
+                                        .getDimensionPixelSize(R.dimen.chooser_service_spacing);
+
         if (DEBUG) {
             Log.d(TAG, "System Time Cost is " + systemCost);
         }
@@ -919,6 +947,10 @@
 
     @Override
     protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
+        if (target instanceof NotSelectableTargetInfo) {
+            return false;
+        }
+
         if (mRefinementIntentSender != null) {
             final Intent fillIn = new Intent();
             final List<Intent> sourceIntents = target.getAllSourceIntents();
@@ -1064,14 +1096,14 @@
             }
         }
 
-        if (!mServiceConnections.isEmpty()) {
-            if (DEBUG) {
-                Log.d(TAG, "queryTargets setting watchdog timer for "
-                        + WATCHDOG_TIMEOUT_MILLIS + "ms");
-            }
-            mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
-                    WATCHDOG_TIMEOUT_MILLIS);
-        } else {
+        if (DEBUG) {
+            Log.d(TAG, "queryTargets setting watchdog timer for "
+                    + WATCHDOG_TIMEOUT_MILLIS + "ms");
+        }
+        mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
+                WATCHDOG_TIMEOUT_MILLIS);
+
+        if (mServiceConnections.isEmpty()) {
             sendVoiceChoicesIfNeeded();
         }
     }
@@ -1213,7 +1245,6 @@
             conn.destroy();
         }
         mServiceConnections.clear();
-        mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
     }
 
     public void onSetupVoiceInteraction() {
@@ -1420,7 +1451,93 @@
         return null;
     }
 
-    final class ChooserTargetInfo implements TargetInfo {
+    interface ChooserTargetInfo extends TargetInfo {
+        float getModifiedScore();
+
+        ChooserTarget getChooserTarget();
+    }
+
+    /**
+      * Distinguish between targets that selectable by the user, vs those that are
+      * placeholders for the system while information is loading in an async manner.
+      */
+    abstract class NotSelectableTargetInfo implements ChooserTargetInfo {
+
+        public Intent getResolvedIntent() {
+            return null;
+        }
+
+        public ComponentName getResolvedComponentName() {
+            return null;
+        }
+
+        public boolean start(Activity activity, Bundle options) {
+            return false;
+        }
+
+        public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+            return false;
+        }
+
+        public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+            return false;
+        }
+
+        public ResolveInfo getResolveInfo() {
+            return null;
+        }
+
+        public CharSequence getDisplayLabel() {
+            return null;
+        }
+
+        public CharSequence getExtendedInfo() {
+            return null;
+        }
+
+        public Drawable getBadgeIcon() {
+            return null;
+        }
+
+        public CharSequence getBadgeContentDescription() {
+            return null;
+        }
+
+        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
+            return null;
+        }
+
+        public List<Intent> getAllSourceIntents() {
+            return null;
+        }
+
+        public boolean isPinned() {
+            return false;
+        }
+
+        public float getModifiedScore() {
+            return 0.1f;
+        }
+
+        public ChooserTarget getChooserTarget() {
+            return null;
+        }
+    }
+
+    final class PlaceHolderTargetInfo extends NotSelectableTargetInfo {
+        public Drawable getDisplayIcon() {
+            return getDrawable(R.drawable.resolver_icon_placeholder);
+        }
+    }
+
+
+    final class EmptyTargetInfo extends NotSelectableTargetInfo {
+        public Drawable getDisplayIcon() {
+            return null;
+        }
+    }
+
+    final class SelectableTargetInfo implements ChooserTargetInfo {
         private final DisplayResolveInfo mSourceInfo;
         private final ResolveInfo mBackupResolveInfo;
         private final ChooserTarget mChooserTarget;
@@ -1431,7 +1548,7 @@
         private final int mFillInFlags;
         private final float mModifiedScore;
 
-        public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget,
+        SelectableTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget,
                 float modifiedScore) {
             mSourceInfo = sourceInfo;
             mChooserTarget = chooserTarget;
@@ -1460,7 +1577,7 @@
             mFillInFlags = 0;
         }
 
-        private ChooserTargetInfo(ChooserTargetInfo other, Intent fillInIntent, int flags) {
+        private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) {
             mSourceInfo = other.mSourceInfo;
             mBackupResolveInfo = other.mBackupResolveInfo;
             mChooserTarget = other.mChooserTarget;
@@ -1616,7 +1733,7 @@
 
         @Override
         public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
-            return new ChooserTargetInfo(this, fillInIntent, flags);
+            return new SelectableTargetInfo(this, fillInIntent, flags);
         }
 
         @Override
@@ -1644,7 +1761,9 @@
         private static final int MAX_SERVICE_TARGETS = 4;
         private static final int MAX_TARGETS_PER_SERVICE = 2;
 
-        private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
+        // Reserve spots for incoming direct share targets by adding placeholders
+        private ChooserTargetInfo mPlaceHolderTargetInfo = new PlaceHolderTargetInfo();
+        private List<ChooserTargetInfo> mServiceTargets;
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
         private boolean mShowServiceTargets;
 
@@ -1663,6 +1782,8 @@
             super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed,
                     resolverListController);
 
+            mServiceTargets = createPlaceHolders();
+
             if (initialIntents != null) {
                 final PackageManager pm = getPackageManager();
                 for (int i = 0; i < initialIntents.length; i++) {
@@ -1715,6 +1836,14 @@
             }
         }
 
+        private List<ChooserTargetInfo> createPlaceHolders() {
+            List<ChooserTargetInfo> list = new ArrayList<>();
+            for (int i = 0; i < MAX_SERVICE_TARGETS; i++) {
+                list.add(mPlaceHolderTargetInfo);
+            }
+            return list;
+        }
+
         @Override
         public boolean showsExtendedInfo(TargetInfo info) {
             // We have badges so we don't need this text shown.
@@ -1770,22 +1899,33 @@
 
         @Override
         public int getCount() {
-            return super.getCount() + getServiceTargetCount() + getCallerTargetCount();
+            return super.getCount() + getSelectableServiceTargetCount() + getCallerTargetCount();
         }
 
         @Override
         public int getUnfilteredCount() {
-            return super.getUnfilteredCount() + getServiceTargetCount() + getCallerTargetCount();
+            return super.getUnfilteredCount() + getSelectableServiceTargetCount()
+                    + getCallerTargetCount();
         }
 
         public int getCallerTargetCount() {
             return mCallerTargets.size();
         }
 
-        public int getServiceTargetCount() {
-            if (!mShowServiceTargets) {
-                return 0;
+        /**
+          * Filter out placeholders and non-selectable service targets
+          */
+        public int getSelectableServiceTargetCount() {
+            int count = 0;
+            for (ChooserTargetInfo info : mServiceTargets) {
+                if (info instanceof SelectableTargetInfo) {
+                    count++;
+                }
             }
+            return count;
+        }
+
+        public int getServiceTargetCount() {
             return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
         }
 
@@ -1831,7 +1971,8 @@
             }
             offset += callerTargetCount;
 
-            final int serviceTargetCount = getServiceTargetCount();
+            final int serviceTargetCount = filtered ? getServiceTargetCount() :
+                                               getSelectableServiceTargetCount();
             if (position - offset < serviceTargetCount) {
                 return mServiceTargets.get(position - offset);
             }
@@ -1850,8 +1991,14 @@
             if (mTargetsNeedPruning && targets.size() > 0) {
                 // First proper update since we got an onListRebuilt() with (transient) 0 items.
                 // Clear out the target list and rebuild.
-                mServiceTargets.clear();
+                mServiceTargets = createPlaceHolders();
                 mTargetsNeedPruning = false;
+
+                // Add back any app-supplied direct share targets that may have been
+                // wiped by this clear
+                if (mCallerChooserTargets != null) {
+                    addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
+                }
             }
 
             final float parentScore = getScore(origTarget);
@@ -1867,7 +2014,7 @@
                     // This incents ChooserTargetServices to define what's truly better.
                     targetScore = lastScore * 0.95f;
                 }
-                insertServiceTarget(new ChooserTargetInfo(origTarget, target, targetScore));
+                insertServiceTarget(new SelectableTargetInfo(origTarget, target, targetScore));
 
                 if (DEBUG) {
                     Log.d(TAG, " => " + target.toString() + " score=" + targetScore
@@ -1889,19 +2036,49 @@
          * Set to true to reveal all service targets at once.
          */
         public void setShowServiceTargets(boolean show) {
+            // mShowServiceTargets is only flipped once to show direct share targets. But after the
+            // initial display the list can be re-sorted and the user will see the target list
+            // change. This will log the initial show and the subsequent shuffle to help us get
+            // accurate timing of the UX.
+            if (show) {
+                getMetricsLogger().write(
+                        new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN_DIRECT_TARGET)
+                                .setSubtype(mShowServiceTargets ? MetricsEvent.PREVIOUSLY_VISIBLE
+                                        : MetricsEvent.PREVIOUSLY_HIDDEN));
+            }
             if (show != mShowServiceTargets) {
                 mShowServiceTargets = show;
                 notifyDataSetChanged();
-                getMetricsLogger().write(
-                        new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN_DIRECT_TARGET));
             }
         }
 
+        /**
+         * Calling this marks service target loading complete, and will attempt to no longer
+         * update the direct share area.
+         */
+        public void completeServiceTargetLoading() {
+            mServiceTargets.removeIf(o -> o instanceof PlaceHolderTargetInfo);
+
+            if (mServiceTargets.isEmpty()) {
+                mServiceTargets.add(new EmptyTargetInfo());
+            }
+            notifyDataSetChanged();
+        }
+
         private void insertServiceTarget(ChooserTargetInfo chooserTargetInfo) {
+            // Avoid inserting any potentially late results
+            if (mServiceTargets.size() == 1
+                    && mServiceTargets.get(0) instanceof EmptyTargetInfo) {
+                return;
+            }
+
             final float newScore = chooserTargetInfo.getModifiedScore();
             for (int i = 0, N = mServiceTargets.size(); i < N; i++) {
                 final ChooserTargetInfo serviceTarget = mServiceTargets.get(i);
-                if (newScore > serviceTarget.getModifiedScore()) {
+                if (serviceTarget == null) {
+                    mServiceTargets.set(i, chooserTargetInfo);
+                    return;
+                } else if (newScore > serviceTarget.getModifiedScore()) {
                     mServiceTargets.add(i, chooserTargetInfo);
                     return;
                 }
@@ -1960,7 +2137,7 @@
 
         // There can be at most one row of service targets.
         public int getServiceTargetRowCount() {
-            return (int) mChooserListAdapter.getServiceTargetCount() == 0 ? 0 : 1;
+            return 1;
         }
 
         @Override
@@ -2046,58 +2223,81 @@
             final int start = getFirstRowPosition(rowPosition);
             final int startType = mChooserListAdapter.getPositionTargetType(start);
 
+            final int lastStartType = mChooserListAdapter.getPositionTargetType(
+                    getFirstRowPosition(rowPosition - 1));
+
+            if (startType != lastStartType || rowPosition == 0) {
+                holder.row.setBackground(mChooserRowLayer);
+                setVertPadding(holder, mChooserRowServiceSpacing, 0);
+            } else {
+                holder.row.setBackground(null);
+                setVertPadding(holder, 0, 0);
+            }
+
             int end = start + mColumnCount - 1;
             while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) {
                 end--;
             }
 
-            if (startType == ChooserListAdapter.TARGET_SERVICE) {
-                int nextStartType = mChooserListAdapter.getPositionTargetType(
-                        getFirstRowPosition(rowPosition + 1));
-                int serviceSpacing = holder.row.getContext().getResources()
-                        .getDimensionPixelSize(R.dimen.chooser_service_spacing);
-                if (rowPosition == 0 && nextStartType != ChooserListAdapter.TARGET_SERVICE) {
-                    // if the row is the only row for target service
-                    setVertPadding(holder, 0, 0);
-                } else {
-                    int top = rowPosition == 0 ? serviceSpacing : 0;
-                    if (nextStartType != ChooserListAdapter.TARGET_SERVICE) {
-                        setVertPadding(holder, top, serviceSpacing);
-                    } else {
-                        setVertPadding(holder, top, 0);
-                    }
-                }
-            } else {
-                holder.row.setBackgroundColor(Color.TRANSPARENT);
-                int lastStartType = mChooserListAdapter.getPositionTargetType(
-                        getFirstRowPosition(rowPosition - 1));
-                if (lastStartType == ChooserListAdapter.TARGET_SERVICE || rowPosition == 0) {
-                    int serviceSpacing = holder.row.getContext().getResources()
-                            .getDimensionPixelSize(R.dimen.chooser_service_spacing);
-                    setVertPadding(holder, serviceSpacing, 0);
-                } else {
-                    setVertPadding(holder, 0, 0);
-                }
-            }
+            if (end == start && mChooserListAdapter.getItem(start) instanceof EmptyTargetInfo) {
+                final TextView textView = holder.row.findViewById(R.id.chooser_row_text_option);
 
-            final int oldHeight = holder.row.getLayoutParams().height;
-            holder.row.getLayoutParams().height = Math.max(1, holder.measuredRowHeight);
-            if (holder.row.getLayoutParams().height != oldHeight) {
-                holder.row.requestLayout();
+                if (textView.getVisibility() != View.VISIBLE) {
+                    textView.setAlpha(0.0f);
+                    textView.setVisibility(View.VISIBLE);
+                    textView.setText(R.string.chooser_no_direct_share_targets);
+
+                    ValueAnimator fadeAnim = ObjectAnimator.ofFloat(textView, "alpha", 0.0f, 1.0f);
+                    fadeAnim.setInterpolator(new DecelerateInterpolator(1.0f));
+
+                    float translationInPx = getResources().getDimensionPixelSize(
+                            R.dimen.chooser_row_text_option_translate);
+                    textView.setTranslationY(translationInPx);
+                    ValueAnimator translateAnim = ObjectAnimator.ofFloat(textView, "translationY",
+                            0.0f);
+                    translateAnim.setInterpolator(new DecelerateInterpolator(1.0f));
+
+                    AnimatorSet animSet = new AnimatorSet();
+                    animSet.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS);
+                    animSet.setStartDelay(NO_DIRECT_SHARE_ANIM_IN_MILLIS);
+                    animSet.playTogether(fadeAnim, translateAnim);
+                    animSet.start();
+                }
             }
 
             for (int i = 0; i < mColumnCount; i++) {
                 final View v = holder.cells[i];
                 if (start + i <= end) {
-                    v.setVisibility(View.VISIBLE);
+                    setCellVisibility(holder, i, View.VISIBLE);
                     holder.itemIndices[i] = start + i;
                     mChooserListAdapter.bindView(holder.itemIndices[i], v);
                 } else {
-                    v.setVisibility(View.INVISIBLE);
+                    setCellVisibility(holder, i, View.INVISIBLE);
                 }
             }
         }
 
+        private void setCellVisibility(RowViewHolder holder, int i, int visibility) {
+            final View v = holder.cells[i];
+            if (visibility == View.VISIBLE) {
+                holder.cellVisibility[i] = true;
+                v.setVisibility(visibility);
+                v.setAlpha(1.0f);
+            } else if (visibility == View.INVISIBLE && holder.cellVisibility[i]) {
+                holder.cellVisibility[i] = false;
+
+                ValueAnimator fadeAnim = ObjectAnimator.ofFloat(v, "alpha", 1.0f, 0f);
+                fadeAnim.setDuration(NO_DIRECT_SHARE_ANIM_IN_MILLIS);
+                fadeAnim.setInterpolator(new AccelerateInterpolator(1.0f));
+                fadeAnim.addListener(new AnimatorListenerAdapter() {
+                    public void onAnimationEnd(Animator animation) {
+                        v.setVisibility(View.INVISIBLE);
+                    }
+                });
+                fadeAnim.start();
+            }
+        }
+
         private void setVertPadding(RowViewHolder holder, int top, int bottom) {
             holder.row.setPadding(holder.row.getPaddingLeft(), top,
                     holder.row.getPaddingRight(), bottom);
@@ -2124,14 +2324,16 @@
     }
 
     static class RowViewHolder {
-        final View[] cells;
-        final ViewGroup row;
+        public final View[] cells;
+        public final boolean [] cellVisibility;
+        public final ViewGroup row;
         int measuredRowHeight;
         int[] itemIndices;
 
         public RowViewHolder(ViewGroup row, int cellCount) {
             this.row = row;
             this.cells = new View[cellCount];
+            this.cellVisibility = new boolean[cellCount];
             this.itemIndices = new int[cellCount];
         }
 
@@ -2209,8 +2411,6 @@
                 mChooserActivity.unbindService(this);
                 mChooserActivity.mServiceConnections.remove(this);
                 if (mChooserActivity.mServiceConnections.isEmpty()) {
-                    mChooserActivity.mChooserHandler.removeMessages(
-                            CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
                     mChooserActivity.sendVoiceChoicesIfNeeded();
                 }
                 mConnectedComponent = null;
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index c096961..c4af4c7 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -48,9 +48,9 @@
     @UnsupportedAppUsage
     List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
     void getHistoricalOps(int uid, String packageName, in List<String> ops, long beginTimeMillis,
-            long endTimeMillis, in RemoteCallback callback);
+            long endTimeMillis, int flags, in RemoteCallback callback);
     void getHistoricalOpsFromDiskRaw(int uid, String packageName, in List<String> ops,
-            long beginTimeMillis, long endTimeMillis, in RemoteCallback callback);
+            long beginTimeMillis, long endTimeMillis, int flags, in RemoteCallback callback);
     void offsetHistory(long duration);
     void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
     void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0919911..011cc04 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -28,6 +28,7 @@
 import android.app.VoiceInteractor.PickOptionRequest;
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.app.VoiceInteractor.Prompt;
+import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -194,7 +195,7 @@
                 com.android.internal.R.string.whichHomeApplicationNamed,
                 com.android.internal.R.string.whichHomeApplicationLabel);
 
-        // SpR.id.buttonecial titles for BROWSABLE components
+        // titles for layout that deals with http(s) intents
         public static final int BROWSABLE_TITLE_RES =
                 com.android.internal.R.string.whichGiveAccessToApplication;
         public static final int BROWSABLE_NAMED_TITLE_RES =
@@ -302,7 +303,7 @@
 
         mUseLayoutForBrowsables = getTargetIntent() == null
                 ? false
-                : getTargetIntent().hasCategory(Intent.CATEGORY_BROWSABLE);
+                : isHttpSchemeAndViewAction(getTargetIntent());
 
         // We don't want to support Always Use if browsable layout is being used,
         // as to mitigate Intent Capturing vulnerability
@@ -473,8 +474,8 @@
         final boolean named = mAdapter.getFilteredPosition() >= 0;
         if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) {
             return getString(defaultTitleRes);
-        } else if (intent.hasCategory(Intent.CATEGORY_BROWSABLE)) {
-            // If the Intent is BROWSABLE then we need to warn the user that
+        } else if (isHttpSchemeAndViewAction(intent)) {
+            // If the Intent's scheme is http(s) then we need to warn the user that
             // they're giving access for the activity to open URLs from this specific host
             return named
                     ? getString(ActionTitle.BROWSABLE_NAMED_TITLE_RES, intent.getData().getHost(),
@@ -583,6 +584,12 @@
         resetButtonBar();
     }
 
+    private boolean isHttpSchemeAndViewAction(Intent intent) {
+        return (IntentFilter.SCHEME_HTTP.equals(intent.getScheme())
+                || IntentFilter.SCHEME_HTTPS.equals(intent.getScheme()))
+                && Intent.ACTION_VIEW.equals(intent.getAction());
+    }
+
     private boolean hasManagedProfile() {
         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
         if (userManager == null) {
@@ -645,10 +652,18 @@
 
     private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
         ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
-        Intent in = new Intent().setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
-                .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-        startActivity(in);
+        Intent intent = new Intent();
+        // For browsers, we open the Default Browser page
+        // For regular apps, we open the Open by Default page
+        if (ri.handleAllWebDataURI) {
+            intent.setAction(Intent.ACTION_MANAGE_DEFAULT_APP)
+                    .putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_BROWSER);
+        } else {
+            intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
+                    .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+        }
+        startActivity(intent);
     }
 
     public void startSelected(int which, boolean always, boolean hasIndexBeenFiltered) {
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index f3bf913..fd74c04 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -81,6 +81,12 @@
      */
     public static final String SSIN_MAX_NUM_ACTIONS = "ssin_max_num_actions";
 
+    /**
+     * The default component of
+     * {@link android.service.notification.NotificationAssistantService}.
+     */
+    public static final String NAS_DEFAULT_SERVICE = "nas_default_service";
+
     // Flags related to media notifications
 
     /**
diff --git a/core/java/com/android/internal/infra/WhitelistHelper.java b/core/java/com/android/internal/infra/WhitelistHelper.java
new file mode 100644
index 0000000..183b465
--- /dev/null
+++ b/core/java/com/android/internal/infra/WhitelistHelper.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.infra;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Helper class for keeping track of whitelisted packages/activities.
+ *
+ * @hide
+ */
+public final class WhitelistHelper {
+
+    private static final String TAG = "WhitelistHelper";
+
+    /**
+     * Map of whitelisted packages/activities. The whole package is whitelisted if its
+     * corresponding value is {@code null}.
+     */
+    @Nullable
+    private ArrayMap<String, ArraySet<ComponentName>> mWhitelistedPackages;
+
+    /**
+     * Sets the whitelist with the given packages and activities. The list is cleared if both
+     * packageNames and components are {@code null}.
+     *
+     * @param packageNames packages to be whitelisted.
+     * @param components activities to be whitelisted.
+     *
+     * @throws IllegalArgumentException if packages or components are empty.
+     */
+    public void setWhitelist(@Nullable ArraySet<String> packageNames,
+            @Nullable ArraySet<ComponentName> components) {
+        mWhitelistedPackages = null;
+        if (packageNames == null && components == null) return;
+
+        if ((packageNames != null && packageNames.isEmpty())
+                || (components != null && components.isEmpty())) {
+            throw new IllegalArgumentException("Packages or Components cannot be empty.");
+        }
+
+        mWhitelistedPackages = new ArrayMap<>();
+
+        if (packageNames != null) {
+            for (int i = 0; i < packageNames.size(); i++) {
+                mWhitelistedPackages.put(packageNames.valueAt(i), null);
+            }
+        }
+
+        if (components != null) {
+            for (int i = 0; i < components.size(); i++) {
+                final ComponentName component = components.valueAt(i);
+                if (component == null) {
+                    Log.w(TAG, "setWhitelist(): component is null");
+                    continue;
+                }
+
+                final String packageName = component.getPackageName();
+                ArraySet<ComponentName> set = mWhitelistedPackages.get(packageName);
+                if (set == null) {
+                    set = new ArraySet<>();
+                    mWhitelistedPackages.put(packageName, set);
+                }
+                set.add(component);
+            }
+        }
+    }
+
+    /**
+     * Helper to use {@link #setWhitelist(ArraySet, ArraySet)} with {@link List Lists}.
+     */
+    public void setWhitelist(@Nullable List<String> packageNames,
+            @Nullable List<ComponentName> components) {
+        final ArraySet<String> packageNamesSet = packageNames == null ? null
+                : new ArraySet<>(packageNames);
+        final ArraySet<ComponentName> componentssSet = components == null ? null
+                : new ArraySet<>(components);
+        setWhitelist(packageNamesSet, componentssSet);
+    }
+
+    /**
+     * Returns {@code true} if the entire package is whitelisted.
+     */
+    public boolean isWhitelisted(@NonNull String packageName) {
+        Preconditions.checkNotNull(packageName);
+
+        if (mWhitelistedPackages == null) return false;
+
+        return mWhitelistedPackages.containsKey(packageName)
+                && mWhitelistedPackages.get(packageName) == null;
+    }
+
+    /**
+     * Returns {@code true} if the specified activity is whitelisted.
+     */
+    public boolean isWhitelisted(@NonNull ComponentName componentName) {
+        Preconditions.checkNotNull(componentName);
+
+        final String packageName = componentName.getPackageName();
+        final ArraySet<ComponentName> whitelistedComponents = getWhitelistedComponents(packageName);
+        if (whitelistedComponents != null) {
+            return whitelistedComponents.contains(componentName);
+        }
+
+        return isWhitelisted(packageName);
+    }
+
+    /**
+     * Returns a set of whitelisted components with the given package, or null if nothing is
+     * whitelisted.
+     */
+    @Nullable
+    public ArraySet<ComponentName> getWhitelistedComponents(@NonNull String packageName) {
+        Preconditions.checkNotNull(packageName);
+
+        return mWhitelistedPackages == null ? null : mWhitelistedPackages.get(packageName);
+    }
+
+    @Override
+    public String toString() {
+        return "WhitelistHelper[" + mWhitelistedPackages + ']';
+    }
+
+    /**
+     * Dumps it!
+     */
+    public void dump(@NonNull String prefix, @NonNull String message, @NonNull PrintWriter pw) {
+        if (mWhitelistedPackages == null || mWhitelistedPackages.size() == 0) {
+            pw.print(prefix); pw.print(message); pw.println(": (no whitelisted packages)");
+            return;
+        }
+
+        final String prefix2 = prefix + "  ";
+        final int size = mWhitelistedPackages.size();
+        pw.print(prefix); pw.print(message); pw.print(": "); pw.print(size);
+        pw.println(" packages");
+        for (int i = 0; i < mWhitelistedPackages.size(); i++) {
+            final String packageName = mWhitelistedPackages.keyAt(i);
+            final ArraySet<ComponentName> components = mWhitelistedPackages.valueAt(i);
+            pw.print(prefix2); pw.print(i); pw.print("."); pw.print(packageName); pw.print(": ");
+            if (components == null) {
+                pw.println("(whole package)");
+                continue;
+            }
+
+            pw.print("["); pw.print(components.valueAt(0));
+            for (int j = 1; j < components.size(); j++) {
+                pw.print(", "); pw.print(components.valueAt(i));
+            }
+            pw.println("]");
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index bab4787..aa1e0d4 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -54,7 +54,7 @@
     public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 1000;
     public static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
     public static final boolean DEFAULT_TRACK_DIRECT_CALLING_UID = true;
-    public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000;
+    public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 1500;
     private static final String DEBUG_ENTRY_PREFIX = "__DEBUG_";
 
     private static class OverflowBinder extends Binder {}
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index c5bc45a..99a1a19 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -115,20 +115,13 @@
         final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
                 classLoaderName, sharedLibraries);
 
-        boolean isForVendor = false;
-        for (String path : dexPath.split(":")) {
-            if (path.startsWith("/vendor/")) {
-                isForVendor = true;
-                break;
-            }
-        }
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
         String errorMessage = createClassloaderNamespace(classLoader,
                                                          targetSdkVersion,
                                                          librarySearchPath,
                                                          libraryPermittedPath,
                                                          isNamespaceShared,
-                                                         isForVendor);
+                                                         dexPath);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
         if (errorMessage != null) {
@@ -144,5 +137,5 @@
                                                             String librarySearchPath,
                                                             String libraryPermittedPath,
                                                             boolean isNamespaceShared,
-                                                            boolean isForVendor);
+                                                            String dexPath);
 }
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
index 718bcb4..b8dfe0d 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
@@ -57,14 +57,14 @@
      * List of UIDs to report data for
      */
     private static final String COLLECTED_UIDS_SETTINGS_KEY = "collected_uids";
-    private static final String COLLECTED_UIDS_DEFAULT = "1000-1000";
+    private static final String COLLECTED_UIDS_DEFAULT = "0-0;1000-1000";
 
     /**
      * Minimum total CPU usage to report
      */
     private static final String MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY =
             "minimum_total_cpu_usage_millis";
-    private static final int MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT = 0;
+    private static final int MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT = 10000;
 
     private final Context mContext;
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index a5e7202..5f23719 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -41,7 +41,6 @@
 import android.system.StructCapUserData;
 import android.system.StructCapUserHeader;
 import android.text.Hyphenator;
-import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -85,8 +84,6 @@
 
     private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
     private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
-    private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
-            "persist.device_config.runtime_native.use_app_image_startup_cache";
 
     private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
     private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
@@ -708,13 +705,6 @@
                 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
             }
 
-            String use_app_image_cache = SystemProperties.get(
-                    PROPERTY_USE_APP_IMAGE_STARTUP_CACHE, "");
-            // Property defaults to true currently.
-            if (!TextUtils.isEmpty(use_app_image_cache) && !use_app_image_cache.equals("false")) {
-                parsedArgs.mRuntimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
-            }
-
             /* Request to fork the system server process */
             pid = Zygote.forkSystemServer(
                     parsedArgs.mUid, parsedArgs.mGid,
diff --git a/core/java/com/android/internal/util/ContrastColorUtil.java b/core/java/com/android/internal/util/ContrastColorUtil.java
index e0ba317f..d037d4b 100644
--- a/core/java/com/android/internal/util/ContrastColorUtil.java
+++ b/core/java/com/android/internal/util/ContrastColorUtil.java
@@ -522,27 +522,6 @@
         return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
     }
 
-    public static int resolveAmbientColor(Context context, int notificationColor) {
-        final int resolvedColor = notificationColor == Notification.COLOR_DEFAULT
-                ? context.getColor(com.android.internal.R.color.notification_default_color_dark)
-                : notificationColor;
-
-        int color = resolvedColor;
-        color = ContrastColorUtil.ensureTextContrastOnBlack(color);
-
-        if (color != resolvedColor) {
-            if (DEBUG){
-                Log.w(TAG, String.format(
-                        "Ambient contrast of notification for %s is %s (over black)"
-                                + " by changing #%s to #%s",
-                        context.getPackageName(),
-                        ContrastColorUtil.contrastChange(resolvedColor, color, Color.BLACK),
-                        Integer.toHexString(resolvedColor), Integer.toHexString(color)));
-            }
-        }
-        return color;
-    }
-
     public static int resolvePrimaryColor(Context context, int backgroundColor,
                                           boolean defaultBackgroundIsDark) {
         boolean useDark = shouldUseDark(backgroundColor, defaultBackgroundIsDark);
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index 498bc5a..de86d92 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -37,7 +38,7 @@
     private final int mNotificationContentImageMarginEnd;
     private ImageView mRightIcon;
     private View mActions;
-    private View mHeader;
+    private NotificationHeaderView mHeader;
     private View mMainColumn;
     private View mMediaContent;
     private int mImagePushIn;
@@ -94,7 +95,14 @@
                 mMainColumn.setLayoutParams(params);
                 reMeasure = true;
             }
-            int headerMarginEnd = size + imageEndMargin;
+            // margin for the entire header line
+            int headerMarginEnd = imageEndMargin;
+            // margin for the header text (not including the expand button and other icons)
+            int headerTextMarginEnd = size + imageEndMargin;
+            if (headerTextMarginEnd != mHeader.getHeaderTextMarginEnd()) {
+                mHeader.setHeaderTextMarginEnd(headerTextMarginEnd);
+                reMeasure = true;
+            }
             params = (MarginLayoutParams) mHeader.getLayoutParams();
             if (params.getMarginEnd() != headerMarginEnd) {
                 params.setMarginEnd(headerMarginEnd);
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 64bdc6e..f48b56d7 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -46,6 +46,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.animation.Interpolator;
+import android.view.inspector.InspectableProperty;
 import android.widget.EdgeEffect;
 import android.widget.Scroller;
 
@@ -2779,6 +2780,9 @@
          * Where to position the view page within the overall ViewPager
          * container; constants are defined in {@link android.view.Gravity}.
          */
+        @InspectableProperty(
+                name = "layout_gravity",
+                valueType = InspectableProperty.ValueType.GRAVITY)
         public int gravity;
 
         /**
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp
index 8dd5f5f..1290026 100644
--- a/core/jni/android/graphics/AnimatedImageDrawable.cpp
+++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp
@@ -35,14 +35,14 @@
 // Note: jpostProcess holds a handle to the ImageDecoder.
 static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
                                            jlong nativeImageDecoder, jobject jpostProcess,
-                                           jint width, jint height, jobject jsubset) {
+                                           jint width, jint height, jlong colorSpaceHandle,
+                                           jboolean extended, jobject jsubset) {
     if (nativeImageDecoder == 0) {
         doThrowIOE(env, "Cannot create AnimatedImageDrawable from null!");
         return 0;
     }
 
     auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
-    const SkISize scaledSize = SkISize::Make(width, height);
     SkIRect subset;
     if (jsubset) {
         GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
@@ -50,15 +50,8 @@
         subset = SkIRect::MakeWH(width, height);
     }
 
-    auto info = imageDecoder->mCodec->getInfo();
     bool hasRestoreFrame = false;
-    if (imageDecoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kWEBP) {
-        if (width < info.width() && height < info.height()) {
-            // WebP will scale its SkBitmap to the scaled size.
-            // FIXME: b/73529447 GIF should do the same.
-            info = info.makeWH(width, height);
-        }
-    } else {
+    if (imageDecoder->mCodec->getEncodedFormat() != SkEncodedImageFormat::kWEBP) {
         const int frameCount = imageDecoder->mCodec->codec()->getFrameCount();
         for (int i = 0; i < frameCount; ++i) {
             SkCodec::FrameInfo frameInfo;
@@ -73,6 +66,12 @@
         }
     }
 
+    auto info = imageDecoder->mCodec->getInfo().makeWH(width, height)
+        .makeColorSpace(GraphicsJNI::getNativeColorSpace(colorSpaceHandle));
+    if (extended) {
+        info = info.makeColorType(kRGBA_F16_SkColorType);
+    }
+
     size_t bytesUsed = info.computeMinByteSize();
     // SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a
     // kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current
@@ -96,7 +95,7 @@
 
 
     sk_sp<SkAnimatedImage> animatedImg = SkAnimatedImage::Make(std::move(imageDecoder->mCodec),
-                                                               scaledSize, subset,
+                                                               info, subset,
                                                                std::move(picture));
     if (!animatedImg) {
         doThrowIOE(env, "Failed to create drawable");
@@ -246,7 +245,7 @@
 }
 
 static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
-    { "nCreate",             "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate },
+    { "nCreate",             "(JLandroid/graphics/ImageDecoder;IIJZLandroid/graphics/Rect;)J",(void*) AnimatedImageDrawable_nCreate },
     { "nGetNativeFinalizer", "()J",                                                          (void*) AnimatedImageDrawable_nGetNativeFinalizer },
     { "nDraw",               "(JJ)J",                                                        (void*) AnimatedImageDrawable_nDraw },
     { "nSetAlpha",           "(JI)V",                                                        (void*) AnimatedImageDrawable_nSetAlpha },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index af2bf2d..89d908b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -463,6 +463,13 @@
     transaction->setColorTransform(surfaceControl, matrix, translation);
 }
 
+static void nativeSetColorSpaceAgnostic(JNIEnv* env, jclass clazz, jlong transactionObj,
+        jlong nativeObject, jboolean agnostic) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+    SurfaceControl* const surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    transaction->setColorSpaceAgnostic(surfaceControl, agnostic);
+}
+
 static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong transactionObj,
         jlong nativeObject,
         jint l, jint t, jint r, jint b) {
@@ -1206,6 +1213,8 @@
             (void*)nativeSetMatrix },
     {"nativeSetColorTransform", "(JJ[F[F)V",
             (void*)nativeSetColorTransform },
+    {"nativeSetColorSpaceAgnostic", "(JJZ)V",
+            (void*)nativeSetColorSpaceAgnostic },
     {"nativeSetFlags", "(JJII)V",
             (void*)nativeSetFlags },
     {"nativeSetWindowCrop", "(JJIIII)V",
diff --git a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
index 9ce3289..f8d41e4 100644
--- a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
+++ b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
@@ -28,16 +28,16 @@
                                               jstring librarySearchPath,
                                               jstring libraryPermittedPath,
                                               jboolean isShared,
-                                              jboolean isForVendor) {
+                                              jstring dexPath) {
     return android::CreateClassLoaderNamespace(env, targetSdkVersion,
                                                classLoader, isShared == JNI_TRUE,
-                                               isForVendor == JNI_TRUE,
+                                               dexPath,
                                                librarySearchPath, libraryPermittedPath);
 }
 
 static const JNINativeMethod g_methods[] = {
     { "createClassloaderNamespace",
-      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;",
+      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;",
       reinterpret_cast<void*>(createClassloaderNamespace_native) },
 };
 
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index efbe8ba..445075d 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -616,7 +616,7 @@
     // OS: Q
     ACTION_PANEL_INTERACTION = 1658;
 
-    // ACTION: Show Contextual homepage, log latency in loading cards
+    // ACTION: Show Contextual homepage. Log total loading latency.
     ACTION_CONTEXTUAL_HOME_SHOW = 1662;
 
     // ACTION: Contextual card displays
@@ -649,6 +649,15 @@
     ACTION_ATCSCUC = 1680;
 
     ACTION_ATCHNUC = 1681;
+
+    // ACTION: Individual contextual card loading time
+    ACTION_CONTEXTUAL_CARD_LOAD = 1684;
+
+    //ACTION: Contextual card loading timeout
+    ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT = 1685;
+
+    //ACTION: Log result for each card's eligibility check
+    ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686;
 }
 
 /**
@@ -2284,4 +2293,10 @@
     PAGE_ATSCP = 1672;
 
     PAGE_ATHNP = 1673;
+
+    // OPEN: Accessibility detail settings (android.settings.ACCESSIBILITY_DETAILS_SETTINGS intent)
+    ACCESSIBILITY_DETAILS_SETTINGS = 1682;
+
+    // Open: Settings will show the conditional when Grayscale mode is on
+    SETTINGS_CONDITION_GRAYSCALE_MODE = 1683;
 }
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c1cbd52..62df6e7 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -1043,7 +1043,9 @@
 
     optional SettingProto app_ops_constants = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
+    optional SettingProto text_classifier_action_model_params = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 145 then 149; // (145 was removed)
+    // Next tag = 149;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0149365..5d24ebc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -398,10 +398,8 @@
 
     <protected-broadcast android:name="android.intent.action.SUB_DEFAULT_CHANGED" />
 
-    <protected-broadcast android:name="android.location.GPS_ENABLED_CHANGE" />
     <protected-broadcast android:name="android.location.PROVIDERS_CHANGED" />
     <protected-broadcast android:name="android.location.MODE_CHANGED" />
-    <protected-broadcast android:name="android.location.GPS_FIX_CHANGE" />
     <protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
 
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
@@ -2002,12 +2000,12 @@
 
     <!-- Must be required by a {@link android.telecom.PhoneAccountSuggestionService},
          to ensure that only the system can bind to it.
-         <p>Protection level: signature|privileged
+         <p>Protection level: signature
          @SystemApi
          @hide
     -->
     <permission android:name="android.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.telecom.CallRedirectionService},
          to ensure that only the system can bind to it.
@@ -2935,6 +2933,13 @@
     <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows an application to launch detail settings activity of a particular
+         accessibility service.
+         <p>Not for use by third-party applications.
+         @hide -->
+    <permission android:name="android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS"
+        android:protectionLevel="signature|installer" />
+
     <!-- @SystemApi Allows an application to watch and control how activities are
          started globally in the system.  Only for is in debugging
          (usually the monkey command).
@@ -3132,6 +3137,14 @@
     <permission android:name="android.permission.BIND_CONTENT_CAPTURE_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- Must be required by a android.service.contentsuggestions.ContentSuggestionsService,
+         to ensure that only the system can bind to it.
+         @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
          to ensure that only the system can bind to it.
          @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
@@ -3951,6 +3964,13 @@
     <permission android:name="android.permission.UPDATE_LOCK"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application the opportunity to become a
+         {@link android.service.notification.NotificationAssistantService}.
+         User permission is still required before access is granted.
+         @hide -->
+    <permission android:name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE"
+                android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi @TestApi Allows an application to read the current set of notifications, including
          any metadata and intents attached.
          @hide -->
@@ -4438,14 +4458,27 @@
          @hide -->
     <permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"
         android:protectionLevel="signature|preinstalled" />
+
     <!-- @SystemApi Allows wallpaper to be rendered in ambient mode.
          @hide -->
     <permission android:name="android.permission.AMBIENT_WALLPAPER"
                 android:protectionLevel="signature|preinstalled" />
+
     <!-- @SystemApi Allows sensor privacy to be modified.
          @hide -->
     <permission android:name="android.permission.MANAGE_SENSOR_PRIVACY"
                 android:protectionLevel="signature" />
+    <!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES}
+         intent.
+         @hide -->
+    <permission android:name="android.permission.REVIEW_ACCESSIBILITY_SERVICES"
+                android:protectionLevel="signature" />
+
+    <!-- @SystemApi Allows an activity to replace the app name and icon displayed in share targets
+         in the sharesheet for the Q-release and later.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"
+                android:protectionLevel="signature|privileged" />
 
     <application android:process="system"
                  android:persistent="true"
diff --git a/core/res/res/drawable/chooser_row_layer_list.xml b/core/res/res/drawable/chooser_row_layer_list.xml
new file mode 100644
index 0000000..0fb26e1
--- /dev/null
+++ b/core/res/res/drawable/chooser_row_layer_list.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:bottom="-2dp" android:left="-2dp" android:right="-2dp">
+        <shape android:shape="rectangle">
+            <stroke android:width="1dp" android:color="@color/chooser_row_divider"/>
+        </shape>
+    </item>
+</layer-list>
diff --git a/core/res/res/layout/chooser_row.xml b/core/res/res/layout/chooser_row.xml
index cf81260..d4585eb 100644
--- a/core/res/res/layout/chooser_row.xml
+++ b/core/res/res/layout/chooser_row.xml
@@ -23,6 +23,12 @@
               android:gravity="start|top"
               android:paddingStart="@dimen/chooser_grid_padding"
               android:paddingEnd="@dimen/chooser_grid_padding">
-
+  <TextView
+      android:id="@+id/chooser_row_text_option"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:gravity="center"
+      android:layout_gravity="center"
+      android:visibility="gone" />
 </LinearLayout>
 
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index b08b0f4..9fd615d 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -59,7 +59,7 @@
             android:paddingStart="48dp"
             android:paddingTop="40dp"
             android:text="@string/immersive_cling_title"
-            android:textColor="@color/primary_text_default_material_light"
+            android:textColor="@android:color/white"
             android:textSize="24sp" />
 
     <TextView
@@ -71,7 +71,7 @@
             android:paddingStart="48dp"
             android:paddingTop="12.6dp"
             android:text="@string/immersive_cling_description"
-            android:textColor="@color/primary_text_default_material_light"
+            android:textColor="@android:color/white"
             android:textSize="16sp" />
 
     <Button
@@ -89,4 +89,4 @@
             android:textColor="@android:color/white"
             android:textSize="14sp" />
 
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index cc7daa8..db2f8d0 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -19,21 +19,6 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <!-- CDMA home system id for Verizon -->
-    <string-array translatable="false" name="config_cdma_home_system">
-        <item>64</item>
-        <item>65</item>
-        <item>66</item>
-        <item>76</item>
-        <item>77</item>
-        <item>78</item>
-        <item>79</item>
-        <item>80</item>
-        <item>81</item>
-        <item>82</item>
-        <item>83</item>
-    </string-array>
-
     <!-- Flag indicating whether the IMS service can be turned off. If false then
         the service will not be turned-off completely (the ImsManager.turnOffIms() will
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 6b8e000..fc7b4cf 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -965,7 +965,7 @@
          <p>The default value of this attribute is <code>false</code>. -->
     <attr name="allowEmbedded" format="boolean" />
 
-    <!-- @hide @SystemApi Specifies whether this {@link android.app.Activity} should be shown on
+    <!-- Specifies whether this {@link android.app.Activity} should be shown on
          top of the lock screen whenever the lockscreen is up and this activity has another
          activity behind it with the {@link android.R.attr#showWhenLocked} attribute set. That
          is, this activity is only visible on the lock screen if there is another activity with
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 02fae4a..e9b1bd3 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -215,4 +215,6 @@
     <!-- Magnifier -->
     <color name="default_magnifier_color_overlay">#00FFFFFF</color>
 
+    <color name="chooser_row_divider">#1f000000</color>
+
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 47e5462..ccd35cd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -654,7 +654,7 @@
     <bool translatable="false" name="config_wifi_framework_enable_associated_network_selection">true</bool>
 
     <!-- Boolean indicating whether single radio chain scan results are to be used for network selection -->
-    <bool translatable="false" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection">false</bool>
+    <bool translatable="false" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection">true</bool>
 
     <!-- Boolean indicating that wifi only link configuratios that have exact same credentials (i.e PSK) -->
     <bool translatable="false" name="config_wifi_only_link_same_credential_configurations">true</bool>
@@ -706,6 +706,9 @@
     <!-- Indicates that connected MAC randomization is supported on this device -->
     <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool>
 
+    <!-- Indicates that p2p MAC randomization is supported on this device -->
+    <bool translatable="false" name="config_wifi_p2p_mac_randomization_supported">false</bool>
+
     <!-- Indicates that wifi link probing is supported on this device -->
     <bool translatable="false" name="config_wifi_link_probing_supported">false</bool>
 
@@ -2917,14 +2920,6 @@
 
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
-    <!-- Home (non-roaming) values for CDMA roaming indicator.
-         Carriers can override this table by resource overlay. If not,
-         the default values come from 3GPP2 C.R1001 table
-         8.1-1. Enhanced Roaming Indicator Number Assignments -->
-    <string-array translatable="false" name="config_cdma_home_system">
-        <item>1</item>
-    </string-array>
-
     <!--From SmsMessage-->
     <!--Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet
         string that's stored in 8-bit unpacked format) characters.-->
@@ -3706,8 +3701,8 @@
 
     <string translatable="false" name="config_batterySaverDeviceSpecificConfig"></string>
 
-    <!-- Package name that should be granted Notification Assistant access -->
-    <string name="config_defaultAssistantAccessPackage" translatable="false">android.ext.services</string>
+    <!-- Component name that should be granted Notification Assistant access -->
+    <string name="config_defaultAssistantAccessComponent" translatable="false">android.ext.services/android.ext.services.notification.Assistant</string>
 
     <bool name="config_supportBluetoothPersistedState">true</bool>
 
@@ -3945,4 +3940,7 @@
      and a second time clipped to the fill level to indicate charge -->
     <bool name="config_batterymeterDualTone">false</bool>
 
+    <!-- The default peak refresh rate for a given device. Change this value if you want to allow
+         for higher refresh rates to be automatically used out of the box -->
+    <integer name="config_defaultPeakRefreshRate">60</integer>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 39cbd26..fafd8fe 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -717,6 +717,7 @@
 
     <!-- chooser (sharesheet) spacing -->
     <dimen name="chooser_corner_radius">8dp</dimen>
+    <dimen name="chooser_row_text_option_translate">25dp</dimen>
     <dimen name="chooser_view_spacing">18dp</dimen>
     <dimen name="chooser_edge_margin_thin">16dp</dimen>
     <dimen name="chooser_edge_margin_normal">24dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 61d53002..b48c6b0 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2934,7 +2934,6 @@
         <public name="foregroundServiceType" />
         <public name="hasFragileUserData" />
         <public name="minAspectRatio" />
-        <!-- @hide @SystemApi -->
         <public name="inheritShowWhenLocked" />
         <public name="zygotePreloadName" />
         <public name="useEmbeddedDex" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4e47b1f..5b658b7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5340,4 +5340,8 @@
         <item quantity="one"><xliff:g id="file_name">%s</xliff:g> + <xliff:g id="count">%d</xliff:g> file</item>
         <item quantity="other"><xliff:g id="file_name">%s</xliff:g> + <xliff:g id="count">%d</xliff:g> files</item>
     </plurals>
+
+    <!-- ChooserActivity - No direct share targets are available. [CHAR LIMIT=NONE] -->
+    <string name="chooser_no_direct_share_targets">Direct share not available</string>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 426d813..e01f421 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1939,6 +1939,7 @@
   <java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" />
   <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
   <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
+  <java-symbol type="bool" name="config_wifi_p2p_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_link_probing_supported" />
   <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
@@ -2606,7 +2607,6 @@
   <java-symbol type="attr" name="lightRadius" />
   <java-symbol type="attr" name="ambientShadowAlpha" />
   <java-symbol type="attr" name="spotShadowAlpha" />
-  <java-symbol type="array" name="config_cdma_home_system" />
   <java-symbol type="bool" name="config_sms_decode_gsm_8bit_data" />
   <java-symbol type="dimen" name="text_size_small_material" />
   <java-symbol type="attr" name="checkMarkGravity" />
@@ -2752,12 +2752,16 @@
   <java-symbol type="id" name="month_view" />
   <java-symbol type="integer" name="config_zen_repeat_callers_threshold" />
   <java-symbol type="dimen" name="chooser_corner_radius" />
+  <java-symbol type="string" name="chooser_no_direct_share_targets" />
+  <java-symbol type="drawable" name="chooser_row_layer_list" />
   <java-symbol type="dimen" name="chooser_view_spacing" />
   <java-symbol type="dimen" name="chooser_edge_margin_thin" />
   <java-symbol type="dimen" name="chooser_edge_margin_normal" />
   <java-symbol type="dimen" name="chooser_preview_image_font_size"/>
   <java-symbol type="dimen" name="chooser_preview_width" />
   <java-symbol type="layout" name="chooser_grid" />
+  <java-symbol type="id" name="chooser_row_text_option" />
+  <java-symbol type="dimen" name="chooser_row_text_option_translate" />
   <java-symbol type="layout" name="resolve_grid_item" />
   <java-symbol type="id" name="day_picker_view_pager" />
   <java-symbol type="layout" name="day_picker_content_material" />
@@ -3533,7 +3537,7 @@
   <java-symbol type="string" name="harmful_app_warning_title" />
   <java-symbol type="layout" name="harmful_app_warning_dialog" />
 
-  <java-symbol type="string" name="config_defaultAssistantAccessPackage" />
+  <java-symbol type="string" name="config_defaultAssistantAccessComponent" />
 
   <java-symbol type="bool" name="config_supportBluetoothPersistedState" />
 
@@ -3688,4 +3692,6 @@
   <java-symbol type="string" name="mime_type_spreadsheet_ext" />
   <java-symbol type="string" name="mime_type_presentation" />
   <java-symbol type="string" name="mime_type_presentation_ext" />
+
+  <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
 </resources>
diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk
index 6b0484e..faffc4b 100644
--- a/core/tests/BroadcastRadioTests/Android.mk
+++ b/core/tests/BroadcastRadioTests/Android.mk
@@ -25,7 +25,7 @@
 # LOCAL_SDK_VERSION := current
 LOCAL_PRIVATE_PLATFORM_APIS := true
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util androidx.test.rules testng
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt androidx.test.rules testng
 
 LOCAL_JAVA_LIBRARIES := android.test.base
 
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index c17aa92..109cff9 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -21,12 +21,14 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
+import android.content.LocusId;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
 import android.media.session.MediaSession;
@@ -320,6 +322,27 @@
                 action.clone().getSemanticAction());
     }
 
+    @Test
+    public void testBuilder_setLocusId() {
+        LocusId locusId = new LocusId("4815162342");
+        Notification notification = new Notification.Builder(mContext, "whatever")
+                .setLocusId(locusId).build();
+        assertEquals(locusId, notification.getLocusId());
+
+        Notification clone = writeAndReadParcelable(notification);
+        assertEquals(locusId, clone.getLocusId());
+    }
+
+    @Test
+    public void testBuilder_setLocusId_null() {
+        Notification notification = new Notification.Builder(mContext, "whatever")
+                .setLocusId(null).build();
+        assertNull(notification.getLocusId());
+
+        Notification clone = writeAndReadParcelable(notification);
+        assertNull(clone.getLocusId());
+    }
+
     private Notification.Builder getMediaNotification() {
         MediaSession session = new MediaSession(mContext, "test");
         return new Notification.Builder(mContext, "color")
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index de1453a..d100f40 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -30,6 +30,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -223,7 +224,29 @@
     }
 
     @Test
-    public void testListener() throws InterruptedException {
+    public void testListener_propertiesCallback() throws InterruptedException {
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+        OnPropertyChangedListener changeListener = new OnPropertyChangedListener() {
+            public void onPropertyChanged(String namespace, String name, String value) {
+                // ignore legacy callback
+            }
+
+            @Override
+            public void onPropertiesChanged(DeviceConfig.Properties properties) {
+                assertThat(properties.getNamespace()).isEqualTo(sNamespace);
+                assertThat(properties.getKeyset().size()).isEqualTo(1);
+                assertThat(properties.getKeyset()).contains(sKey);
+                assertThat(properties.getString(sKey, "default_value")).isEqualTo(sValue);
+                countDownLatch.countDown();
+            }
+        };
+
+        testListener(countDownLatch, changeListener);
+    }
+
+    @Test
+    public void testListener_legacyCallback() throws InterruptedException {
         CountDownLatch countDownLatch = new CountDownLatch(1);
 
         OnPropertyChangedListener changeListener = (namespace, name, value) -> {
@@ -233,16 +256,23 @@
             countDownLatch.countDown();
         };
 
+        testListener(countDownLatch, changeListener);
+
+    }
+
+    private void testListener(CountDownLatch countDownLatch,
+            OnPropertyChangedListener changeListener) {
         try {
             DeviceConfig.addOnPropertyChangedListener(sNamespace,
                     ActivityThread.currentApplication().getMainExecutor(), changeListener);
             DeviceConfig.setProperty(sNamespace, sKey, sValue, false);
             assertThat(countDownLatch.await(
                     WAIT_FOR_PROPERTY_CHANGE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+        } catch (InterruptedException e) {
+            Assert.fail(e.getMessage());
         } finally {
             DeviceConfig.removeOnPropertyChangedListener(changeListener);
         }
-
     }
 
     private static boolean deleteViaContentProvider(String namespace, String key) {
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 69632c1..67e364b 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -92,7 +92,8 @@
                     Settings.System.VOLUME_SYSTEM, // deprecated since API 2?
                     Settings.System.VOLUME_VOICE, // deprecated since API 2?
                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
-                    Settings.System.WINDOW_ORIENTATION_LISTENER_LOG // used for debugging only
+                    Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only
+                    Settings.System.PEAK_REFRESH_RATE // depends on hardware capabilities
                     );
 
     private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
@@ -116,7 +117,6 @@
                     Settings.Global.ANOMALY_CONFIG_VERSION,
                     Settings.Global.APN_DB_UPDATE_CONTENT_URL,
                     Settings.Global.APN_DB_UPDATE_METADATA_URL,
-                    Settings.Global.APPLY_RAMPING_RINGER,
                     Settings.Global.APP_BINDING_CONSTANTS,
                     Settings.Global.APP_IDLE_CONSTANTS,
                     Settings.Global.APP_OPS_CONSTANTS,
@@ -131,6 +131,7 @@
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
                     Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED,
+                    Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST,
                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
                     Settings.Global.BROADCAST_BG_CONSTANTS,
                     Settings.Global.BROADCAST_FG_CONSTANTS,
@@ -466,6 +467,7 @@
                     Settings.Global.TETHER_SUPPORTED,
                     Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER,
                     Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
+                    Settings.Global.TEXT_CLASSIFIER_ACTION_MODEL_PARAMS,
                     Settings.Global.THEATER_MODE_ON,
                     Settings.Global.TIME_ONLY_MODE_CONSTANTS,
                     Settings.Global.TRANSITION_ANIMATION_SCALE,
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index a5ac270..de2edc3 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -25,7 +25,6 @@
 import static org.testng.Assert.assertThrows;
 
 import android.content.LocusId;
-import android.net.Uri;
 import android.os.Parcel;
 import android.os.SystemClock;
 import android.view.autofill.AutofillId;
@@ -47,7 +46,7 @@
 
     private static final long MY_EPOCH = SystemClock.uptimeMillis();
 
-    private static final LocusId ID = new LocusId(Uri.parse("WHATEVER"));
+    private static final LocusId ID = new LocusId("WHATEVER");
 
     // Not using @Mock because it's final - no need to be fancy here....
     private final ContentCaptureContext mClientContext =
diff --git a/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java b/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java
new file mode 100644
index 0000000..1b3c724
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/ConfigParserTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.textclassifier;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.provider.DeviceConfig;
+import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ConfigParserTest {
+    private static final String SETTINGS = "int=42,float=12.3,boolean=true,string=abc";
+    private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
+            "device_config delete " + DeviceConfig.NAMESPACE_TEXTCLASSIFIER;
+    private static final String[] DEVICE_CONFIG_KEYS = new String[]{
+            "boolean",
+            "string",
+            "int",
+            "float"
+    };
+
+    private ConfigParser mConfigParser;
+
+    @Before
+    public void setup() throws IOException {
+        mConfigParser = new ConfigParser(SETTINGS);
+        clearDeviceConfig();
+    }
+
+    @After
+    public void tearDown() throws IOException {
+        clearDeviceConfig();
+    }
+
+    @Test
+    public void getBoolean_deviceConfig() {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                "boolean",
+                "false",
+                false);
+        boolean value = mConfigParser.getBoolean("boolean", true);
+        assertThat(value).isFalse();
+    }
+
+    @Test
+    public void getBoolean_settings() {
+        boolean value = mConfigParser.getBoolean(
+                "boolean",
+                false);
+        assertThat(value).isTrue();
+    }
+
+    @Test
+    public void getInt_deviceConfig() {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                "int",
+                "1",
+                false);
+        int value = mConfigParser.getInt("int", 0);
+        assertThat(value).isEqualTo(1);
+    }
+
+    @Test
+    public void getInt_settings() {
+        int value = mConfigParser.getInt("int", 0);
+        assertThat(value).isEqualTo(42);
+    }
+
+    @Test
+    public void getFloat_deviceConfig() {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                "float",
+                "3.14",
+                false);
+        float value = mConfigParser.getFloat("float", 0);
+        assertThat(value).isWithin(0.0001f).of(3.14f);
+    }
+
+    @Test
+    public void getFloat_settings() {
+        float value = mConfigParser.getFloat("float", 0);
+        assertThat(value).isWithin(0.0001f).of(12.3f);
+    }
+
+    @Test
+    public void getString_deviceConfig() {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                "string",
+                "hello",
+                false);
+        String value = mConfigParser.getString("string", "");
+        assertThat(value).isEqualTo("hello");
+    }
+
+    @Test
+    public void getString_settings() {
+        String value = mConfigParser.getString("string", "");
+        assertThat(value).isEqualTo("abc");
+    }
+
+    private static void clearDeviceConfig() throws IOException {
+        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        for (String key : DEVICE_CONFIG_KEYS) {
+            uiDevice.executeShellCommand(CLEAR_DEVICE_CONFIG_KEY_CMD + " " + key);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 9fbc166..3578bc0 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -740,6 +740,7 @@
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
+        sendIntent.setType("text/plain");
         return sendIntent;
     }
 
diff --git a/core/tests/coretests/src/com/android/internal/infra/WhitelistHelperTest.java b/core/tests/coretests/src/com/android/internal/infra/WhitelistHelperTest.java
new file mode 100644
index 0000000..ab6830b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/infra/WhitelistHelperTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.infra;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.ComponentName;
+import android.util.ArraySet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/**
+ * Unit test for {@link WhitelistHelper}.
+ *
+ * <p>To run it:
+ * {@code atest FrameworksCoreTests:com.android.internal.infra.WhitelistHelperTest}
+ */
+
+@RunWith(MockitoJUnitRunner.class)
+public class WhitelistHelperTest {
+    private WhitelistHelper mWhitelistHelper = new WhitelistHelper();
+
+    private String mPackage1 = "com.example";
+    private String mPackage2 = "com.example2";
+
+    private ComponentName mComponent1 = new ComponentName(mPackage1, "class1");
+    private ComponentName mComponent2 = new ComponentName(mPackage1, "class2");
+    private ComponentName mComponentDifferentPkg = new ComponentName(mPackage2, "class3");
+
+    @Test
+    public void testSetWhitelist_emptyArguments() {
+        assertThrows(IllegalArgumentException.class,
+                () -> mWhitelistHelper.setWhitelist(new ArraySet<>(), null));
+        assertThrows(IllegalArgumentException.class,
+                () -> mWhitelistHelper.setWhitelist(null, new ArraySet<>()));
+        assertThrows(IllegalArgumentException.class,
+                () -> mWhitelistHelper.setWhitelist(new ArraySet<>(), new ArraySet<>()));
+    }
+
+    @Test
+    public void testWhitelistHelper_nullArguments() {
+        assertThrows(NullPointerException.class,
+                () -> mWhitelistHelper.isWhitelisted((String) null));
+        assertThrows(NullPointerException.class,
+                () -> mWhitelistHelper.isWhitelisted((ComponentName) null));
+        assertThrows(NullPointerException.class,
+                () -> mWhitelistHelper.getWhitelistedComponents(null));
+    }
+
+    @Test
+    public void testSetWhitelist_nullPackage() {
+        final ArraySet<String> packages = new ArraySet<>();
+        packages.add(null);
+        mWhitelistHelper.setWhitelist(packages, null);
+
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
+
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
+    }
+
+    @Test
+    public void testSetWhitelist_nullActivity() {
+        final ArraySet<ComponentName> components = new ArraySet<>();
+        components.add(null);
+        mWhitelistHelper.setWhitelist(null, components);
+
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
+
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
+    }
+
+    @Test
+    public void testSetWhitelist_replaceWhitelist() {
+        final ArraySet<ComponentName> components = new ArraySet<>();
+        components.add(mComponent1);
+        mWhitelistHelper.setWhitelist(null, components);
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
+
+        final ArraySet<ComponentName> components2 = new ArraySet<>();
+        components2.add(mComponent2);
+        mWhitelistHelper.setWhitelist(null, components2);
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isTrue();
+    }
+
+    @Test
+    public void testIsWhitelisted_packageWhitelisted() {
+        final ArraySet<String> packages = new ArraySet<>();
+        packages.add(mPackage1);
+        mWhitelistHelper.setWhitelist(packages, null);
+
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isTrue();
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
+
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isTrue();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
+    }
+
+    @Test
+    public void testIsWhitelisted_activityWhitelisted() {
+        final ArraySet<ComponentName> components = new ArraySet<>();
+        components.add(mComponent1);
+        mWhitelistHelper.setWhitelist(null, components);
+
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage1)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mPackage2)).isFalse();
+
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent1)).isTrue();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponent2)).isFalse();
+        assertThat(mWhitelistHelper.isWhitelisted(mComponentDifferentPkg)).isFalse();
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
index 5dddd1a..e6e7a85 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -518,6 +518,17 @@
     }
 
     @Test
+    public void testUidPredicate_zero() {
+        KernelCpuThreadReaderSettingsObserver.UidPredicate uidPredicate =
+                KernelCpuThreadReaderSettingsObserver.UidPredicate.fromString("0-0");
+        assertTrue(uidPredicate.test(0));
+        assertFalse(uidPredicate.test(1));
+        assertFalse(uidPredicate.test(2000));
+        assertFalse(uidPredicate.test(10000));
+        assertFalse(uidPredicate.test(-100));
+    }
+
+    @Test
     public void testUidPredicate_emptyRangeString() {
         assertThrows(
                 NumberFormatException.class,
diff --git a/core/xsd/Android.bp b/core/xsd/Android.bp
new file mode 100644
index 0000000..81669eb
--- /dev/null
+++ b/core/xsd/Android.bp
@@ -0,0 +1,6 @@
+xsd_config {
+    name: "permission",
+    srcs: ["permission.xsd"],
+    api_dir: "schema",
+    package_name: "com.android.xml.permission",
+}
diff --git a/core/xsd/permission.xsd b/core/xsd/permission.xsd
new file mode 100644
index 0000000..d90863b
--- /dev/null
+++ b/core/xsd/permission.xsd
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="permissions">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="group" type="group" maxOccurs="unbounded"/>
+                <xs:element name="permission" type="permission" maxOccurs="unbounded"/>
+                <xs:element name="assign-permission" type="assign-permission" maxOccurs="unbounded"/>
+                <xs:element name="split-permission" type="split-permission" maxOccurs="unbounded"/>
+                <xs:element name="library" type="library" maxOccurs="unbounded"/>
+                <xs:element name="feature" type="feature" maxOccurs="unbounded"/>
+                <xs:element name="unavailable-feature" type="unavailable-feature" maxOccurs="unbounded"/>
+                <xs:element name="allow-in-power-save-except-idle" type="allow-in-power-save-except-idle" maxOccurs="unbounded"/>
+                <xs:element name="allow-in-power-save" type="allow-in-power-save" maxOccurs="unbounded"/>
+                <xs:element name="allow-in-data-usage-save" type="allow-in-data-usage-save" maxOccurs="unbounded"/>
+                <xs:element name="allow-unthrottled-location" type="allow-unthrottled-location" maxOccurs="unbounded"/>
+                <xs:element name="allow-ignore-location-settings" type="allow-ignore-location-settings" maxOccurs="unbounded"/>
+                <xs:element name="allow-implicit-broadcast" type="allow-implicit-broadcast" maxOccurs="unbounded"/>
+                <xs:element name="app-link" type="app-link" maxOccurs="unbounded"/>
+                <xs:element name="system-user-whitelisted-app" type="system-user-whitelisted-app" maxOccurs="unbounded"/>
+                <xs:element name="system-user-blacklisted-app" type="system-user-blacklisted-app" maxOccurs="unbounded"/>
+                <xs:element name="default-enabled-vr-app" type="default-enabled-vr-app" maxOccurs="unbounded"/>
+                <xs:element name="backup-transport-whitelisted-service" type="backup-transport-whitelisted-service" maxOccurs="unbounded"/>
+                <xs:element name="disabled-until-used-preinstalled-carrier-associated-app" type="disabled-until-used-preinstalled-carrier-associated-app" maxOccurs="unbounded"/>
+                <xs:element name="disabled-until-used-preinstalled-carrier-app" type="disabled-until-used-preinstalled-carrier-app" maxOccurs="unbounded"/>
+                <xs:element name="privapp-permissions" type="privapp-permissions" maxOccurs="unbounded"/>
+                <xs:element name="oem-permissions" type="oem-permissions" maxOccurs="unbounded"/>
+                <xs:element name="hidden-api-whitelisted-app" type="hidden-api-whitelisted-app" maxOccurs="unbounded"/>
+                <xs:element name="allow-association" type="allow-association" maxOccurs="unbounded"/>
+                <xs:element name="bugreport-whitelisted" type="bugreport-whitelisted" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:complexType name="group">
+        <xs:attribute name="gid" type="xs:int"/>
+    </xs:complexType>
+    <xs:complexType name="permission">
+        <xs:attribute name="name" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="assign-permission">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="uid" type="xs:int"/>
+    </xs:complexType>
+    <xs:complexType name="split-permission">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="targetSdk" type="xs:int"/>
+        <xs:sequence>
+            <xs:element name="library" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:string"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="library">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="file" type="xs:string"/>
+        <xs:attribute name="dependency" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="feature">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="notLowRam" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="unavailable-feature">
+        <xs:attribute name="name" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-in-power-save-except-idle">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-in-power-save">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-in-data-usage-save">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-unthrottled-location">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-ignore-location-settings">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-implicit-broadcast">
+        <xs:attribute name="action" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="app-link">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="system-user-whitelisted-app">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="system-user-blacklisted-app">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="default-enabled-vr-app">
+        <xs:attribute name="package" type="xs:string"/>
+        <xs:attribute name="class" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="backup-transport-whitelisted-service">
+        <xs:attribute name="service" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="disabled-until-used-preinstalled-carrier-associated-app">
+        <xs:attribute name="package" type="xs:string"/>
+        <xs:attribute name="carrierAppPackage" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="disabled-until-used-preinstalled-carrier-app">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="privapp-permissions">
+        <xs:attribute name="package" type="xs:string"/>
+        <xs:sequence>
+            <xs:element name="permission" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:string"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="deny-permission" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:string"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="oem-permissions">
+        <xs:attribute name="package" type="xs:string"/>
+        <xs:sequence>
+            <xs:element name="permission" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:string"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="deny-permission" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:string"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="hidden-api-whitelisted-app">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="allow-association">
+        <xs:attribute name="target" type="xs:string"/>
+        <xs:attribute name="allowed" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="bugreport-whitelisted">
+        <xs:attribute name="package" type="xs:string"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/core/xsd/schema/README.md b/core/xsd/schema/README.md
new file mode 100644
index 0000000..f52d93d
--- /dev/null
+++ b/core/xsd/schema/README.md
@@ -0,0 +1 @@
+Please see the [README](https://android.googlesource.com/platform/system/tools/xsdc/+/refs/heads/master/README.md) for details regarding the Configfile as API.
diff --git a/core/xsd/schema/current.txt b/core/xsd/schema/current.txt
new file mode 100644
index 0000000..82bb0fea
--- /dev/null
+++ b/core/xsd/schema/current.txt
@@ -0,0 +1,242 @@
+// Signature format: 2.0
+package com.android.xml.permission {
+
+  public class AllowAssociation {
+    ctor public AllowAssociation();
+    method public String getAllowed();
+    method public String getTarget();
+    method public void setAllowed(String);
+    method public void setTarget(String);
+  }
+
+  public class AllowIgnoreLocationSettings {
+    ctor public AllowIgnoreLocationSettings();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AllowImplicitBroadcast {
+    ctor public AllowImplicitBroadcast();
+    method public String getAction();
+    method public void setAction(String);
+  }
+
+  public class AllowInDataUsageSave {
+    ctor public AllowInDataUsageSave();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AllowInPowerSave {
+    ctor public AllowInPowerSave();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AllowInPowerSaveExceptIdle {
+    ctor public AllowInPowerSaveExceptIdle();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AllowUnthrottledLocation {
+    ctor public AllowUnthrottledLocation();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AppLink {
+    ctor public AppLink();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class AssignPermission {
+    ctor public AssignPermission();
+    method public String getName();
+    method public int getUid();
+    method public void setName(String);
+    method public void setUid(int);
+  }
+
+  public class BackupTransportWhitelistedService {
+    ctor public BackupTransportWhitelistedService();
+    method public String getService();
+    method public void setService(String);
+  }
+
+  public class BugreportWhitelisted {
+    ctor public BugreportWhitelisted();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class DefaultEnabledVrApp {
+    ctor public DefaultEnabledVrApp();
+    method public String get_class();
+    method public String get_package();
+    method public void set_class(String);
+    method public void set_package(String);
+  }
+
+  public class DisabledUntilUsedPreinstalledCarrierApp {
+    ctor public DisabledUntilUsedPreinstalledCarrierApp();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class DisabledUntilUsedPreinstalledCarrierAssociatedApp {
+    ctor public DisabledUntilUsedPreinstalledCarrierAssociatedApp();
+    method public String getCarrierAppPackage();
+    method public String get_package();
+    method public void setCarrierAppPackage(String);
+    method public void set_package(String);
+  }
+
+  public class Feature {
+    ctor public Feature();
+    method public String getName();
+    method public String getNotLowRam();
+    method public void setName(String);
+    method public void setNotLowRam(String);
+  }
+
+  public class Group {
+    ctor public Group();
+    method public int getGid();
+    method public void setGid(int);
+  }
+
+  public class HiddenApiWhitelistedApp {
+    ctor public HiddenApiWhitelistedApp();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class Library {
+    ctor public Library();
+    method public String getDependency();
+    method public String getFile();
+    method public String getName();
+    method public void setDependency(String);
+    method public void setFile(String);
+    method public void setName(String);
+  }
+
+  public class OemPermissions {
+    ctor public OemPermissions();
+    method public java.util.List<com.android.xml.permission.OemPermissions.DenyPermission> getDenyPermission();
+    method public java.util.List<com.android.xml.permission.OemPermissions.Permission> getPermission();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public static class OemPermissions.DenyPermission {
+    ctor public OemPermissions.DenyPermission();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public static class OemPermissions.Permission {
+    ctor public OemPermissions.Permission();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public class Permission {
+    ctor public Permission();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public class Permissions {
+    ctor public Permissions();
+    method public java.util.List<com.android.xml.permission.AllowAssociation> getAllowAssociation();
+    method public java.util.List<com.android.xml.permission.AllowIgnoreLocationSettings> getAllowIgnoreLocationSettings();
+    method public java.util.List<com.android.xml.permission.AllowImplicitBroadcast> getAllowImplicitBroadcast();
+    method public java.util.List<com.android.xml.permission.AllowInDataUsageSave> getAllowInDataUsageSave();
+    method public java.util.List<com.android.xml.permission.AllowInPowerSave> getAllowInPowerSave();
+    method public java.util.List<com.android.xml.permission.AllowInPowerSaveExceptIdle> getAllowInPowerSaveExceptIdle();
+    method public java.util.List<com.android.xml.permission.AllowUnthrottledLocation> getAllowUnthrottledLocation();
+    method public java.util.List<com.android.xml.permission.AppLink> getAppLink();
+    method public java.util.List<com.android.xml.permission.AssignPermission> getAssignPermission();
+    method public java.util.List<com.android.xml.permission.BackupTransportWhitelistedService> getBackupTransportWhitelistedService();
+    method public java.util.List<com.android.xml.permission.BugreportWhitelisted> getBugreportWhitelisted();
+    method public java.util.List<com.android.xml.permission.DefaultEnabledVrApp> getDefaultEnabledVrApp();
+    method public java.util.List<com.android.xml.permission.DisabledUntilUsedPreinstalledCarrierApp> getDisabledUntilUsedPreinstalledCarrierApp();
+    method public java.util.List<com.android.xml.permission.DisabledUntilUsedPreinstalledCarrierAssociatedApp> getDisabledUntilUsedPreinstalledCarrierAssociatedApp();
+    method public java.util.List<com.android.xml.permission.Feature> getFeature();
+    method public java.util.List<com.android.xml.permission.Group> getGroup();
+    method public java.util.List<com.android.xml.permission.HiddenApiWhitelistedApp> getHiddenApiWhitelistedApp();
+    method public java.util.List<com.android.xml.permission.Library> getLibrary();
+    method public java.util.List<com.android.xml.permission.OemPermissions> getOemPermissions();
+    method public java.util.List<com.android.xml.permission.Permission> getPermission();
+    method public java.util.List<com.android.xml.permission.PrivappPermissions> getPrivappPermissions();
+    method public java.util.List<com.android.xml.permission.SplitPermission> getSplitPermission();
+    method public java.util.List<com.android.xml.permission.SystemUserBlacklistedApp> getSystemUserBlacklistedApp();
+    method public java.util.List<com.android.xml.permission.SystemUserWhitelistedApp> getSystemUserWhitelistedApp();
+    method public java.util.List<com.android.xml.permission.UnavailableFeature> getUnavailableFeature();
+  }
+
+  public class PrivappPermissions {
+    ctor public PrivappPermissions();
+    method public java.util.List<com.android.xml.permission.PrivappPermissions.DenyPermission> getDenyPermission();
+    method public java.util.List<com.android.xml.permission.PrivappPermissions.Permission> getPermission();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public static class PrivappPermissions.DenyPermission {
+    ctor public PrivappPermissions.DenyPermission();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public static class PrivappPermissions.Permission {
+    ctor public PrivappPermissions.Permission();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public class SplitPermission {
+    ctor public SplitPermission();
+    method public java.util.List<com.android.xml.permission.SplitPermission.Library> getLibrary();
+    method public String getName();
+    method public int getTargetSdk();
+    method public void setName(String);
+    method public void setTargetSdk(int);
+  }
+
+  public static class SplitPermission.Library {
+    ctor public SplitPermission.Library();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public class SystemUserBlacklistedApp {
+    ctor public SystemUserBlacklistedApp();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class SystemUserWhitelistedApp {
+    ctor public SystemUserWhitelistedApp();
+    method public String get_package();
+    method public void set_package(String);
+  }
+
+  public class UnavailableFeature {
+    ctor public UnavailableFeature();
+    method public String getName();
+    method public void setName(String);
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static com.android.xml.permission.Permissions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/core/xsd/schema/last_current.txt b/core/xsd/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/xsd/schema/last_current.txt
diff --git a/core/xsd/schema/last_removed.txt b/core/xsd/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/xsd/schema/last_removed.txt
diff --git a/core/xsd/schema/removed.txt b/core/xsd/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/core/xsd/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index 2110a8f..3e53a38 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -33,6 +33,7 @@
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
         <permission name="android.permission.MASTER_CLEAR"/>
+        <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.MOVE_PACKAGE"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index f19e44c..fcd5d56 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -23,6 +23,7 @@
     <privapp-permissions package="android.ext.services">
         <permission name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
         <permission name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" />
+        <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.apps.tag">
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 18eafa6..2e56e09 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1718,6 +1718,11 @@
      * <p>Modifies the bitmap to have the specified {@link ColorSpace}, without
      * affecting the underlying allocation backing the bitmap.</p>
      *
+     * <p>This affects how the framework will interpret the color at each pixel. A bitmap
+     * with {@link Config#ALPHA_8} never has a color space, since a color space does not
+     * affect the alpha channel. Other {@code Config}s must always have a non-null
+     * {@code ColorSpace}.</p>
+     *
      * @throws IllegalArgumentException If the specified color space is {@code null}, not
      *         {@link ColorSpace.Model#RGB RGB}, has a transfer function that is not an
      *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or whose
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index e623354..7345ea4 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -193,7 +193,7 @@
      *
      * @param name The debug name to use for this HardwareRenderer instance
      */
-    public void setName(String name) {
+    public void setName(@NonNull String name) {
         nSetName(mNativeProxy, name);
     }
 
@@ -330,7 +330,7 @@
          *
          * @return this instance
          */
-        public FrameRenderRequest setVsyncTime(long vsyncTime) {
+        public @NonNull FrameRenderRequest setVsyncTime(long vsyncTime) {
             mFrameInfo.setVsync(vsyncTime, vsyncTime);
             mFrameInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
             return this;
@@ -351,7 +351,7 @@
          *
          * @return this instance
          */
-        public FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
+        public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor,
                 @NonNull Runnable frameCommitCallback) {
             setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback));
             return this;
@@ -372,7 +372,7 @@
          *                   completion.
          * @return this instance
          */
-        public FrameRenderRequest setWaitForPresent(boolean shouldWait) {
+        public @NonNull FrameRenderRequest setWaitForPresent(boolean shouldWait) {
             mWaitForPresent = shouldWait;
             return this;
         }
@@ -406,7 +406,7 @@
      * @return An instance of {@link FrameRenderRequest}. The instance may be reused for every
      * frame, so the caller should not hold onto it for longer than a single render request.
      */
-    public FrameRenderRequest createRenderRequest() {
+    public @NonNull FrameRenderRequest createRenderRequest() {
         mRenderRequest.reset();
         return mRenderRequest;
     }
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 7016cc7..2d5babc 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -59,6 +59,8 @@
 import java.io.InputStream;
 import java.lang.annotation.Retention;
 import java.nio.ByteBuffer;
+import java.util.Locale;
+import java.util.Objects;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -838,6 +840,40 @@
     }
 
     /**
+     * Return if the given MIME type is a supported file format that can be
+     * decoded by this class. This can be useful to determine if a file can be
+     * decoded directly, or if it needs to be converted into a more general
+     * format using an API like {@link ContentResolver#openTypedAssetFile}.
+     */
+    public static boolean isMimeTypeSupported(@NonNull String mimeType) {
+        Objects.requireNonNull(mimeType);
+        switch (mimeType.toLowerCase(Locale.US)) {
+            case "image/png":
+            case "image/jpeg":
+            case "image/webp":
+            case "image/gif":
+            case "image/heif":
+            case "image/heic":
+            case "image/bmp":
+            case "image/x-ico":
+            case "image/vnd.wap.wbmp":
+            case "image/x-sony-arw":
+            case "image/x-canon-cr2":
+            case "image/x-adobe-dng":
+            case "image/x-nikon-nef":
+            case "image/x-nikon-nrw":
+            case "image/x-olympus-orf":
+            case "image/x-fuji-raf":
+            case "image/x-panasonic-rw2":
+            case "image/x-pentax-pef":
+            case "image/x-samsung-srw":
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
      * Create a new {@link Source Source} from a resource.
      *
      * @param res the {@link Resources} object containing the image data.
@@ -1606,14 +1642,16 @@
         mTempStorage = null;
     }
 
-    private void checkState() {
+    private void checkState(boolean animated) {
         if (mNativePtr == 0) {
             throw new IllegalStateException("Cannot use closed ImageDecoder!");
         }
 
         checkSubset(mDesiredWidth, mDesiredHeight, mCropRect);
 
-        if (mAllocator == ALLOCATOR_HARDWARE) {
+        // animated ignores the allocator, so no need to check for incompatible
+        // fields.
+        if (!animated && mAllocator == ALLOCATOR_HARDWARE) {
             if (mMutable) {
                 throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
             }
@@ -1637,21 +1675,30 @@
         }
     }
 
+    private boolean checkForExtended() {
+        if (mDesiredColorSpace == null) {
+            return false;
+        }
+        return mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)
+                || mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
+    }
+
+    private long getColorSpacePtr() {
+        if (mDesiredColorSpace == null) {
+            return 0;
+        }
+        return mDesiredColorSpace.getNativeInstance();
+    }
+
     @WorkerThread
     @NonNull
     private Bitmap decodeBitmapInternal() throws IOException {
-        checkState();
-        long colorSpacePtr = 0;
-        boolean extended = false;
-        if (mDesiredColorSpace != null) {
-            colorSpacePtr = mDesiredColorSpace.getNativeInstance();
-            extended = mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)
-                || mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
-        }
+        checkState(false);
         return nDecodeBitmap(mNativePtr, this, mPostProcessor != null,
                 mDesiredWidth, mDesiredHeight, mCropRect,
                 mMutable, mAllocator, mUnpremultipliedRequired,
-                mConserveMemory, mDecodeAsAlphaMask, colorSpacePtr, extended);
+                mConserveMemory, mDecodeAsAlphaMask, getColorSpacePtr(),
+                checkForExtended());
     }
 
     private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
@@ -1717,9 +1764,11 @@
                 // mPostProcessor exists.
                 ImageDecoder postProcessPtr = decoder.mPostProcessor == null ?
                         null : decoder;
+                decoder.checkState(true);
                 Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
                         postProcessPtr, decoder.mDesiredWidth,
-                        decoder.mDesiredHeight, srcDensity,
+                        decoder.mDesiredHeight, decoder.getColorSpacePtr(),
+                        decoder.checkForExtended(), srcDensity,
                         src.computeDstDensity(), decoder.mCropRect,
                         decoder.mInputStream, decoder.mAssetFd);
                 // d has taken ownership of these objects.
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 30466e1..c0e0a24 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -166,7 +166,9 @@
      * @param drawGLFunction A native function pointer
      *
      * @hide
+     * @deprecated Use {@link #drawWebViewFunctor(int)}
      */
+    @Deprecated
     public void callDrawGLFunction2(long drawGLFunction) {
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction, null);
     }
@@ -184,7 +186,9 @@
      * canvas's display list has been released.
      *
      * @hide
+     * @deprecated Use {@link #drawWebViewFunctor(int)}
      */
+    @Deprecated
     public void drawGLFunctor2(long drawGLFunctor, @Nullable Runnable releasedCallback) {
         nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
     }
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 42b6acd..c3bcbb4 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -62,7 +62,7 @@
  *
  * <h3>Creating a RenderNode</h3>
  * <pre class="prettyprint">
- *     RenderNode renderNode = RenderNode.create("myRenderNode");
+ *     RenderNode renderNode = new RenderNode("myRenderNode");
  *     renderNode.setLeftTopRightBottom(0, 0, 50, 50); // Set the size to 50x50
  *     RecordingCanvas canvas = renderNode.beginRecording();
  *     try {
@@ -106,7 +106,7 @@
  *
  * <pre class="prettyprint">
  *     private void createDisplayList() {
- *         mRenderNode = RenderNode.create("MyRenderNode");
+ *         mRenderNode = new RenderNode("MyRenderNode");
  *         mRenderNode.setLeftTopRightBottom(0, 0, width, height);
  *         RecordingCanvas canvas = mRenderNode.beginRecording();
  *         try {
@@ -338,7 +338,7 @@
      * @see #endRecording()
      * @see #hasDisplayList()
      */
-    public RecordingCanvas beginRecording(int width, int height) {
+    public @NonNull RecordingCanvas beginRecording(int width, int height) {
         if (mCurrentRecordingCanvas != null) {
             throw new IllegalStateException(
                     "Recording currently in progress - missing #endRecording() call?");
@@ -358,7 +358,7 @@
      * @see #endRecording()
      * @see #hasDisplayList()
      */
-    public RecordingCanvas beginRecording() {
+    public @NonNull RecordingCanvas beginRecording() {
         return beginRecording(nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
     }
 
@@ -1285,7 +1285,7 @@
      * @param position The position rectangle in pixels
      * @return True if the value changed, false if the new value was the same as the previous value.
      */
-    public boolean setPosition(Rect position) {
+    public boolean setPosition(@NonNull Rect position) {
         return nSetLeftTopRightBottom(mNativeRenderNode,
                 position.left, position.top, position.right, position.bottom);
     }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index 3aaec31..bb6bf24 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -291,8 +291,8 @@
      */
     public AnimatedImageDrawable(long nativeImageDecoder,
             @Nullable ImageDecoder decoder, int width, int height,
-            int srcDensity, int dstDensity, Rect cropRect,
-            InputStream inputStream, AssetFileDescriptor afd)
+            long colorSpaceHandle, boolean extended, int srcDensity, int dstDensity,
+            Rect cropRect, InputStream inputStream, AssetFileDescriptor afd)
             throws IOException {
         width = Bitmap.scaleFromDensity(width, srcDensity, dstDensity);
         height = Bitmap.scaleFromDensity(height, srcDensity, dstDensity);
@@ -309,8 +309,8 @@
             mIntrinsicHeight = cropRect.height();
         }
 
-        mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect),
-                inputStream, afd);
+        mState = new State(nCreate(nativeImageDecoder, decoder, width, height, colorSpaceHandle,
+                    extended, cropRect), inputStream, afd);
 
         final long nativeSize = nNativeByteSize(mState.mNativePtr);
         NativeAllocationRegistry registry = new NativeAllocationRegistry(
@@ -574,8 +574,8 @@
 
 
     private static native long nCreate(long nativeImageDecoder,
-            @Nullable ImageDecoder decoder, int width, int height, Rect cropRect)
-        throws IOException;
+            @Nullable ImageDecoder decoder, int width, int height, long colorSpaceHandle,
+            boolean extended, Rect cropRect) throws IOException;
     @FastNative
     private static native long nGetNativeFinalizer();
     private static native long nDraw(long nativePtr, long canvasNativePtr);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 6ecb621..e58e802 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -17,9 +17,11 @@
 package android.graphics.drawable;
 
 import android.annotation.ColorInt;
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.Px;
 import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
@@ -581,9 +583,9 @@
      * The default value for this property is {@code false}.
      * <p>
      * <strong>Note</strong>: This property corresponds to the
-     * {@code android:useLevel} attribute on the inner {@code &lt;gradient&gt;}
+     * {@code android:useLevel} attribute on the inner {@code <gradient>}
      * tag, NOT the {@code android:useLevel} attribute on the outer
-     * {@code &lt;shape&gt;} tag. For example,
+     * {@code <shape>} tag. For example,
      * <pre>{@code
      * <shape ...>
      *     <gradient
@@ -670,7 +672,7 @@
      * @see #mutate()
      * @see #setColor(int)
      */
-    public void setColors(@ColorInt int[] colors) {
+    public void setColors(@Nullable @ColorInt int[] colors) {
         setColors(colors, null);
     }
 
@@ -690,7 +692,7 @@
      * @see #mutate()
      * @see #setColors(int[])
      */
-    public void setColors(@ColorInt int[] colors, @Nullable float[] offsets) {
+    public void setColors(@Nullable @ColorInt int[] colors, @Nullable float[] offsets) {
         mGradientState.setGradientColors(colors);
         mGradientState.mPositions = offsets;
         mGradientIsDirty = true;
@@ -877,7 +879,11 @@
      * @see #getInnerRadiusRatio()
      * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
      */
-    public void setInnerRadiusRatio(float innerRadiusRatio) {
+    public void setInnerRadiusRatio(
+            @FloatRange(from = 0.0f, fromInclusive = false) float innerRadiusRatio) {
+        if (innerRadiusRatio <= 0) {
+            throw new IllegalArgumentException("Ratio must be greater than zero");
+        }
         mGradientState.mInnerRadiusRatio = innerRadiusRatio;
         mPathIsDirty = true;
         invalidateSelf();
@@ -899,7 +905,7 @@
      * @see #getInnerRadius()
      * @attr ref android.R.styleable#GradientDrawable_innerRadius
      */
-    public void setInnerRadius(int innerRadius) {
+    public void setInnerRadius(@Px int innerRadius) {
         mGradientState.mInnerRadius = innerRadius;
         mPathIsDirty = true;
         invalidateSelf();
@@ -911,7 +917,7 @@
      * @see #setInnerRadius(int)
      * @attr ref android.R.styleable#GradientDrawable_innerRadius
      */
-    public int getInnerRadius() {
+    public @Px int getInnerRadius() {
         return mGradientState.mInnerRadius;
     }
 
@@ -921,7 +927,11 @@
      * @see #getThicknessRatio()
      * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
      */
-    public void setThicknessRatio(float thicknessRatio) {
+    public void setThicknessRatio(
+            @FloatRange(from = 0.0f, fromInclusive = false) float thicknessRatio) {
+        if (thicknessRatio <= 0) {
+            throw new IllegalArgumentException("Ratio must be greater than zero");
+        }
         mGradientState.mThicknessRatio = thicknessRatio;
         mPathIsDirty = true;
         invalidateSelf();
@@ -942,7 +952,7 @@
      *
      * @attr ref android.R.styleable#GradientDrawable_thickness
      */
-    public void setThickness(int thickness) {
+    public void setThickness(@Px int thickness) {
         mGradientState.mThickness = thickness;
         mPathIsDirty = true;
         invalidateSelf();
@@ -954,7 +964,7 @@
      * @see #setThickness(int)
      * @attr ref android.R.styleable#GradientDrawable_thickness
      */
-    public int getThickness() {
+    public @Px int getThickness() {
         return mGradientState.mThickness;
     }
 
@@ -970,7 +980,7 @@
      * @attr ref android.R.styleable#GradientDrawablePadding_right
      * @attr ref android.R.styleable#GradientDrawablePadding_bottom
      */
-    public void setPadding(int left, int top, int right, int bottom) {
+    public void setPadding(@Px int left, @Px int top, @Px int right, @Px int bottom) {
         if (mGradientState.mPadding == null) {
             mGradientState.mPadding = new Rect();
         }
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 2855227..f67188c 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -256,7 +256,7 @@
      * @see #getStateCount()
      * @see #getStateDrawable(int)
      */
-    public int[] getStateSet(int index) {
+    public @NonNull int[] getStateSet(int index) {
         return mStateListState.mStateSets[index];
     }
 
@@ -268,7 +268,7 @@
      * @see #getStateCount()
      * @see #getStateSet(int)
      */
-    public Drawable getStateDrawable(int index) {
+    public @Nullable Drawable getStateDrawable(int index) {
         return mStateListState.getChild(index);
     }
 
@@ -280,7 +280,7 @@
      * @see #getStateDrawable(int)
      * @see #getStateSet(int)
      */
-    public int findStateDrawableIndex(int[] stateSet) {
+    public int findStateDrawableIndex(@NonNull int[] stateSet) {
         return mStateListState.indexOfStateSet(stateSet);
     }
 
diff --git a/keystore/java/android/security/keystore/DeviceIdAttestationException.java b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
index 13f50b1..8ba0317 100644
--- a/keystore/java/android/security/keystore/DeviceIdAttestationException.java
+++ b/keystore/java/android/security/keystore/DeviceIdAttestationException.java
@@ -16,6 +16,7 @@
 
 package android.security.keystore;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 
@@ -33,7 +34,7 @@
      *
      * @param detailMessage the detail message for this exception.
      */
-    public DeviceIdAttestationException(String detailMessage) {
+    public DeviceIdAttestationException(@Nullable String detailMessage) {
         super(detailMessage);
     }
 
@@ -44,7 +45,7 @@
      * @param message the detail message for this exception.
      * @param cause the cause of this exception, may be {@code null}.
      */
-    public DeviceIdAttestationException(String message, Throwable cause) {
+    public DeviceIdAttestationException(@Nullable String message, @Nullable Throwable cause) {
         super(message, cause);
     }
 }
diff --git a/keystore/tests/Android.mk b/keystore/tests/Android.mk
index 596e5f5..99d3197 100644
--- a/keystore/tests/Android.mk
+++ b/keystore/tests/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test
+    androidx.test.rules hamcrest-library
 
 LOCAL_PACKAGE_NAME := KeystoreTests
 LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/keystore/tests/AndroidManifest.xml b/keystore/tests/AndroidManifest.xml
index 9bf2d0c..6833cd1 100644
--- a/keystore/tests/AndroidManifest.xml
+++ b/keystore/tests/AndroidManifest.xml
@@ -20,7 +20,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="android.security.tests"
         android:label="Tests for Keystore">
     </instrumentation>
diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
index 32f8ec4..fca2775 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -22,16 +22,20 @@
 
 import android.os.Parcel;
 import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.ParcelableKeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.support.test.runner.AndroidJUnit4;
+import android.security.keystore.ParcelableKeyGenParameterSpec;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.math.BigInteger;
 import java.security.spec.ECGenParameterSpec;
 import java.security.spec.RSAKeyGenParameterSpec;
 import java.util.Date;
+
 import javax.security.auth.x500.X500Principal;
-import org.junit.Test;
-import org.junit.runner.RunWith;
 
 /** Unit tests for {@link ParcelableKeyGenParameterSpec}. */
 @RunWith(AndroidJUnit4.class)
diff --git a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
index 865cad4..b2edfd0 100644
--- a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
@@ -20,10 +20,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
+import android.security.ParcelableKeyGenParameterSpecTest;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.security.ParcelableKeyGenParameterSpecTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 117d05e..d74f27c 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -1052,6 +1052,8 @@
 }
 
 void AssetManager2::InvalidateCaches(uint32_t diff) {
+  cached_bag_resid_stacks_.clear();
+
   if (diff == 0xffffffffu) {
     // Everything must go.
     cached_bags_.clear();
diff --git a/libs/hwui/TEST_MAPPING b/libs/hwui/TEST_MAPPING
new file mode 100644
index 0000000..d9f2acb
--- /dev/null
+++ b/libs/hwui/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsUiRenderingTestCases"
+    },
+    {
+      "name": "CtsGraphicsTestCases"
+    },
+    {
+      "name": "CtsAccelerationTestCases"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index 5e8eac1..f056d3b 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -47,12 +47,16 @@
     void setAll(bool all);
     void setDest(int dest);
     void addSection(int section);
+    void setReceiverPkg(const string& pkg);
+    void setReceiverCls(const string& cls);
     void addHeader(const vector<uint8_t>& headerProto);
 
     inline bool all() const { return mAll; }
     bool containsSection(int section) const;
     inline int dest() const { return mDest; }
     inline const set<int>& sections() const { return mSections; }
+    inline const String16& receiverPkg() const { return mReceiverPkg; }
+    inline const String16& receiverCls() const { return mReceiverCls; }
     inline const vector<vector<uint8_t>>& headers() const { return mHeaders; }
 
     void merge(const IncidentReportArgs& that);
@@ -62,6 +66,8 @@
     vector<vector<uint8_t>> mHeaders;
     bool mAll;
     int mDest;
+    String16 mReceiverPkg;
+    String16 mReceiverCls;
 };
 
 }
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index 06b7a5b..46c8dcf9 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -81,6 +81,16 @@
         return err;
     }
 
+    err = out->writeString16(mReceiverPkg);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    err = out->writeString16(mReceiverCls);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
     return NO_ERROR;
 }
 
@@ -134,6 +144,9 @@
     }
     mDest = dest;
 
+    mReceiverPkg = in->readString16();
+    mReceiverCls = in->readString16();
+
     return OK;
 }
 
@@ -161,6 +174,18 @@
 }
 
 void
+IncidentReportArgs::setReceiverPkg(const string& pkg)
+{
+    mReceiverPkg = String16(pkg.c_str());
+}
+
+void
+IncidentReportArgs::setReceiverCls(const string& cls)
+{
+    mReceiverCls = String16(cls.c_str());
+}
+
+void
 IncidentReportArgs::addHeader(const vector<uint8_t>& headerProto)
 {
     mHeaders.push_back(headerProto);
diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java
index fdbc3dd..3e32c21 100644
--- a/location/java/android/location/GnssMeasurementCorrections.java
+++ b/location/java/android/location/GnssMeasurementCorrections.java
@@ -16,11 +16,16 @@
 
 package android.location;
 
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -35,37 +40,44 @@
 public final class GnssMeasurementCorrections implements Parcelable {
 
     /** Represents latitude in degrees at which the corrections are computed. */
-    private double mLatitudeDegrees;
+    @FloatRange(from = -90.0f, to = 90.0f)
+    private final double mLatitudeDegrees;
     /** Represents longitude in degrees at which the corrections are computed. */
-    private double mLongitudeDegrees;
+    @FloatRange(from = -180.0f, to = 180.0f)
+    private final double mLongitudeDegrees;
     /**
      * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
      * are computed.
      */
-    private double mAltitudeMeters;
+    @FloatRange(from = -1000.0, to = 10000.0f)
+    private final double mAltitudeMeters;
     /**
      * Represents the horizontal uncertainty (68% confidence) in meters on the device position at
      * which the corrections are provided.
      *
      * <p> This value is useful for example to judge how accurate the provided corrections are.
      */
-    private double mHorizontalPositionUncertaintyMeters;
+    @FloatRange(from = 0.0f)
+    private final double mHorizontalPositionUncertaintyMeters;
     /**
      * Represents the vertical uncertainty (68% confidence) in meters on the device position at
      * which the corrections are provided.
      *
      * <p> This value is useful for example to judge how accurate the provided corrections are.
      */
-    private double mVerticalPositionUncertaintyMeters;
+    @FloatRange(from = 0.0f)
+    private final double mVerticalPositionUncertaintyMeters;
 
     /** Time Of Applicability, GPS time of week in nanoseconds. */
-    private long mToaGpsNanosecondsOfWeek;
+    @IntRange(from = 0)
+    private final long mToaGpsNanosecondsOfWeek;
 
     /**
      * A set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
      * satellite in view.
      */
-    private @Nullable List<GnssSingleSatCorrection> mSingleSatCorrectionList;
+    @NonNull
+    private final List<GnssSingleSatCorrection> mSingleSatCorrectionList;
 
     private GnssMeasurementCorrections(Builder builder) {
         mLatitudeDegrees = builder.mLatitudeDegrees;
@@ -74,19 +86,19 @@
         mHorizontalPositionUncertaintyMeters = builder.mHorizontalPositionUncertaintyMeters;
         mVerticalPositionUncertaintyMeters = builder.mVerticalPositionUncertaintyMeters;
         mToaGpsNanosecondsOfWeek = builder.mToaGpsNanosecondsOfWeek;
-        mSingleSatCorrectionList =
-                builder.mSingleSatCorrectionList == null
-                        ? null
-                        : Collections.unmodifiableList(
-                                new ArrayList<>(builder.mSingleSatCorrectionList));
+        final List<GnssSingleSatCorrection> singleSatCorrList =  builder.mSingleSatCorrectionList;
+        Preconditions.checkArgument(singleSatCorrList != null && !singleSatCorrList.isEmpty());
+        mSingleSatCorrectionList = Collections.unmodifiableList(new ArrayList<>(singleSatCorrList));
     }
 
     /** Gets the latitude in degrees at which the corrections are computed. */
+    @FloatRange(from = -90.0f, to = 90.0f)
     public double getLatitudeDegrees() {
         return mLatitudeDegrees;
     }
 
     /** Gets the longitude in degrees at which the corrections are computed. */
+    @FloatRange(from = -180.0f, to = 180.0f)
     public double getLongitudeDegrees() {
         return mLongitudeDegrees;
     }
@@ -95,6 +107,7 @@
      * Gets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections are
      * computed.
      */
+    @FloatRange(from = -1000.0f, to = 10000.0f)
     public double getAltitudeMeters() {
         return mAltitudeMeters;
     }
@@ -103,6 +116,7 @@
      * Gets the horizontal uncertainty (68% confidence) in meters on the device position at
      * which the corrections are provided.
      */
+    @FloatRange(from = 0.0f)
     public double getHorizontalPositionUncertaintyMeters() {
         return mHorizontalPositionUncertaintyMeters;
     }
@@ -111,11 +125,13 @@
      * Gets the vertical uncertainty (68% confidence) in meters on the device position at
      * which the corrections are provided.
      */
+    @FloatRange(from = 0.0f)
     public double getVerticalPositionUncertaintyMeters() {
         return mVerticalPositionUncertaintyMeters;
     }
 
     /** Gets the time of applicability, GPS time of week in nanoseconds. */
+    @IntRange(from = 0)
     public long getToaGpsNanosecondsOfWeek() {
         return mToaGpsNanosecondsOfWeek;
     }
@@ -124,7 +140,8 @@
      * Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
      * satellite in view
      */
-    public @Nullable List<GnssSingleSatCorrection> getSingleSatelliteCorrectionList() {
+    @NonNull
+    public List<GnssSingleSatCorrection> getSingleSatelliteCorrectionList() {
         return mSingleSatCorrectionList;
     }
 
@@ -133,10 +150,11 @@
         return 0;
     }
 
-    public static final @android.annotation.NonNull Creator<GnssMeasurementCorrections> CREATOR =
+    public static final Creator<GnssMeasurementCorrections> CREATOR =
             new Creator<GnssMeasurementCorrections>() {
                 @Override
-                public GnssMeasurementCorrections createFromParcel(Parcel parcel) {
+                @NonNull
+                public GnssMeasurementCorrections createFromParcel(@NonNull Parcel parcel) {
                     final GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
                             new Builder()
                                     .setLatitudeDegrees(parcel.readDouble())
@@ -148,7 +166,7 @@
                     List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
                     parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
                     gnssMeasurementCorrectons.setSingleSatelliteCorrectionList(
-                            singleSatCorrectionList.isEmpty() ? null : singleSatCorrectionList);
+                            singleSatCorrectionList);
                     return gnssMeasurementCorrectons.build();
                 }
 
@@ -177,7 +195,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel parcel, int flags) {
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeDouble(mLatitudeDegrees);
         parcel.writeDouble(mLongitudeDegrees);
         parcel.writeDouble(mAltitudeMeters);
@@ -199,16 +217,18 @@
         private double mHorizontalPositionUncertaintyMeters;
         private double mVerticalPositionUncertaintyMeters;
         private long mToaGpsNanosecondsOfWeek;
-        private List<GnssSingleSatCorrection> mSingleSatCorrectionList;
+        @Nullable private List<GnssSingleSatCorrection> mSingleSatCorrectionList;
 
         /** Sets the latitude in degrees at which the corrections are computed. */
-        public Builder setLatitudeDegrees(double latitudeDegrees) {
+        @NonNull public Builder setLatitudeDegrees(
+                @FloatRange(from = -90.0f, to = 90.0f) double latitudeDegrees) {
             mLatitudeDegrees = latitudeDegrees;
             return this;
         }
 
         /** Sets the longitude in degrees at which the corrections are computed. */
-        public Builder setLongitudeDegrees(double longitudeDegrees) {
+        @NonNull public Builder setLongitudeDegrees(
+                @FloatRange(from = -180.0f, to = 180.0f) double longitudeDegrees) {
             mLongitudeDegrees = longitudeDegrees;
             return this;
         }
@@ -217,7 +237,8 @@
          * Sets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections
          * are computed.
          */
-        public Builder setAltitudeMeters(double altitudeMeters) {
+        @NonNull public Builder setAltitudeMeters(
+                @FloatRange(from = -1000.0f, to = 10000.0f) double altitudeMeters) {
             mAltitudeMeters = altitudeMeters;
             return this;
         }
@@ -227,8 +248,8 @@
          * Sets the horizontal uncertainty (68% confidence) in meters on the device position at
          * which the corrections are provided.
          */
-        public Builder setHorizontalPositionUncertaintyMeters(
-                double horizontalPositionUncertaintyMeters) {
+        @NonNull public Builder setHorizontalPositionUncertaintyMeters(
+                @FloatRange(from = 0.0f) double horizontalPositionUncertaintyMeters) {
             mHorizontalPositionUncertaintyMeters = horizontalPositionUncertaintyMeters;
             return this;
         }
@@ -237,14 +258,15 @@
          * Sets the vertical uncertainty (68% confidence) in meters on the device position at which
          * the corrections are provided.
          */
-        public Builder setVerticalPositionUncertaintyMeters(
-                double verticalPositionUncertaintyMeters) {
+        @NonNull public Builder setVerticalPositionUncertaintyMeters(
+                @FloatRange(from = 0.0f) double verticalPositionUncertaintyMeters) {
             mVerticalPositionUncertaintyMeters = verticalPositionUncertaintyMeters;
             return this;
         }
 
         /** Sets the time of applicability, GPS time of week in nanoseconds. */
-        public Builder setToaGpsNanosecondsOfWeek(long toaGpsNanosecondsOfWeek) {
+        @NonNull public Builder setToaGpsNanosecondsOfWeek(
+                @IntRange(from = 0) long toaGpsNanosecondsOfWeek) {
             mToaGpsNanosecondsOfWeek = toaGpsNanosecondsOfWeek;
             return this;
         }
@@ -253,19 +275,14 @@
          * Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for
          * a satellite in view
          */
-        public Builder setSingleSatelliteCorrectionList(
-                @Nullable List<GnssSingleSatCorrection> singleSatCorrectionList) {
-            if (singleSatCorrectionList == null) {
-                mSingleSatCorrectionList = null;
-            } else {
-                mSingleSatCorrectionList =
-                        Collections.unmodifiableList(new ArrayList<>(singleSatCorrectionList));
-            }
+        @NonNull public Builder setSingleSatelliteCorrectionList(
+                @NonNull List<GnssSingleSatCorrection> singleSatCorrectionList) {
+            mSingleSatCorrectionList = singleSatCorrectionList;
             return this;
         }
 
         /** Builds a {@link GnssMeasurementCorrections} instance as specified by this builder. */
-        public GnssMeasurementCorrections build() {
+        @NonNull public GnssMeasurementCorrections build() {
             return new GnssMeasurementCorrections(this);
         }
     }
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
index c5095d7..9d05287 100644
--- a/location/java/android/location/GnssReflectingPlane.java
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -16,6 +16,8 @@
 
 package android.location;
 
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -29,17 +31,21 @@
 public final class GnssReflectingPlane implements Parcelable {
 
     /** Represents latitude in degrees of the reflecting plane */
-    private double mLatitudeDegrees;
+    @FloatRange(from = -90.0f, to = 90.0f)
+    private final double mLatitudeDegrees;
     /** Represents longitude in degrees of the reflecting plane. */
-    private double mLongitudeDegrees;
+    @FloatRange(from = -180.0f, to = 180.0f)
+    private final double mLongitudeDegrees;
     /**
      * Represents altitude in meters above the WGS 84 reference ellipsoid of the reflection point in
      * the plane
      */
-    private double mAltitudeMeters;
+    @FloatRange(from = -1000.0f, to = 10000.0f)
+    private final double mAltitudeMeters;
 
     /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
-    private double mAzimuthDegrees;
+    @FloatRange(from = 0.0f, to = 360.0f)
+    private final double mAzimuthDegrees;
 
     private GnssReflectingPlane(Builder builder) {
         mLatitudeDegrees = builder.mLatitudeDegrees;
@@ -49,11 +55,13 @@
     }
 
     /** Gets the latitude in degrees of the reflecting plane. */
+    @FloatRange(from = -90.0f, to = 90.0f)
     public double getLatitudeDegrees() {
         return mLatitudeDegrees;
     }
 
     /** Gets the longitude in degrees of the reflecting plane. */
+    @FloatRange(from = -180.0f, to = 180.0f)
     public double getLongitudeDegrees() {
         return mLongitudeDegrees;
     }
@@ -62,11 +70,13 @@
      * Gets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point
      * within the plane
      */
+    @FloatRange(from = -1000.0f, to = 10000.0f)
     public double getAltitudeMeters() {
         return mAltitudeMeters;
     }
 
     /** Gets the azimuth clockwise from north of the reflecting plane in degrees. */
+    @FloatRange(from = 0.0f, to = 360.0f)
     public double getAzimuthDegrees() {
         return mAzimuthDegrees;
     }
@@ -76,10 +86,11 @@
         return 0;
     }
 
-    public static final @android.annotation.NonNull Creator<GnssReflectingPlane> CREATOR =
+    public static final Creator<GnssReflectingPlane> CREATOR =
             new Creator<GnssReflectingPlane>() {
                 @Override
-                public GnssReflectingPlane createFromParcel(Parcel parcel) {
+                @NonNull
+                public GnssReflectingPlane createFromParcel(@NonNull Parcel parcel) {
                     GnssReflectingPlane reflectingPlane =
                             new Builder()
                                     .setLatitudeDegrees(parcel.readDouble())
@@ -108,7 +119,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel parcel, int flags) {
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeDouble(mLatitudeDegrees);
         parcel.writeDouble(mLongitudeDegrees);
         parcel.writeDouble(mAltitudeMeters);
@@ -119,19 +130,20 @@
     public static final class Builder {
         /** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
         private double mLatitudeDegrees;
-
         private double mLongitudeDegrees;
         private double mAltitudeMeters;
         private double mAzimuthDegrees;
 
         /** Sets the latitude in degrees of the reflecting plane. */
-        public Builder setLatitudeDegrees(double latitudeDegrees) {
+        @NonNull public Builder setLatitudeDegrees(
+                @FloatRange(from = -90.0f, to = 90.0f) double latitudeDegrees) {
             mLatitudeDegrees = latitudeDegrees;
             return this;
         }
 
         /** Sets the longitude in degrees of the reflecting plane. */
-        public Builder setLongitudeDegrees(double longitudeDegrees) {
+        @NonNull public Builder setLongitudeDegrees(
+                @FloatRange(from = -180.0f, to = 180.0f) double longitudeDegrees) {
             mLongitudeDegrees = longitudeDegrees;
             return this;
         }
@@ -140,19 +152,21 @@
          * Sets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point
          * within the plane
          */
-        public Builder setAltitudeMeters(double altitudeMeters) {
+        @NonNull public Builder setAltitudeMeters(
+                @FloatRange(from = -1000.0f, to = 10000.0f) double altitudeMeters) {
             mAltitudeMeters = altitudeMeters;
             return this;
         }
 
         /** Sets the azimuth clockwise from north of the reflecting plane in degrees. */
-        public Builder setAzimuthDegrees(double azimuthDegrees) {
+        @NonNull public Builder setAzimuthDegrees(
+                @FloatRange(from = 0.0f, to = 360.0f) double azimuthDegrees) {
             mAzimuthDegrees = azimuthDegrees;
             return this;
         }
 
         /** Builds a {@link GnssReflectingPlane} object as specified by this builder. */
-        public GnssReflectingPlane build() {
+        @NonNull public GnssReflectingPlane build() {
             return new GnssReflectingPlane(this);
         }
     }
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
index dbf3fd9..e901909 100644
--- a/location/java/android/location/GnssSingleSatCorrection.java
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -17,6 +17,8 @@
 package android.location;
 
 import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
@@ -35,40 +37,49 @@
     /**
      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
      * #mProbSatIsLos}.
+     *
+     * @hide
      */
     public static final int HAS_PROB_SAT_IS_LOS_MASK = 1 << 0;
 
     /**
      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
      * #mExcessPathLengthMeters}.
+     *
+     * @hide
      */
     public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1;
 
     /**
      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
      * #mExcessPathLengthUncertaintyMeters}.
+     *
+     * @hide
      */
     public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2;
 
     /**
      * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
      * #mReflectingPlane}.
+     *
+     * @hide
      */
     public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3;
 
     /** A bitmask of fields present in this object (see HAS_* constants defined above) */
-    private int mSingleSatCorrectionFlags;
+    private final int mSingleSatCorrectionFlags;
 
     /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
     @GnssStatus.ConstellationType
-    private int mConstellationType;
+    private final int mConstellationType;
 
     /**
      * Satellite vehicle ID number
      *
      * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}.
      */
-    private int mSatId;
+    @IntRange(from = 0)
+    private final int mSatId;
 
     /**
      * Carrier frequency of the signal to be corrected, for example it can be the GPS center
@@ -79,22 +90,25 @@
      * values related to L1 will be filled, and in the other all of the values related to L5 will be
      * filled.
      */
-    private float mCarrierFrequencyHz;
+    @FloatRange(from = 0.0f,  fromInclusive = false)
+    private final float mCarrierFrequencyHz;
 
     /**
      * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
      * location.
      */
-    @FloatRange(from = 0f, to = 1f)
-    private float mProbSatIsLos;
+    @FloatRange(from = 0.0f, to = 1.0f)
+    private final float mProbSatIsLos;
 
     /**
      * Excess path length to be subtracted from pseudorange before using it in calculating location.
      */
-    private float mExcessPathLengthMeters;
+    @FloatRange(from = 0.0f)
+    private final float mExcessPathLengthMeters;
 
     /** Error estimate (1-sigma) for the Excess path length estimate */
-    private float mExcessPathLengthUncertaintyMeters;
+    @FloatRange(from = 0.0f)
+    private final float mExcessPathLengthUncertaintyMeters;
 
     /**
      * Defines the reflecting plane location and azimuth information
@@ -102,7 +116,8 @@
      * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
      * signal goes through multiple reflections or if reflection plane serving is not supported.
      */
-    private @Nullable GnssReflectingPlane mReflectingPlane;
+    @Nullable
+    private final GnssReflectingPlane mReflectingPlane;
 
     private GnssSingleSatCorrection(Builder builder) {
         mSingleSatCorrectionFlags = builder.mSingleSatCorrectionFlags;
@@ -115,7 +130,11 @@
         mReflectingPlane = builder.mReflectingPlane;
     }
 
-    /** Gets a bitmask of fields present in this object */
+    /**
+     * Gets a bitmask of fields present in this object
+     *
+     * @hide
+     */
     public int getSingleSatelliteCorrectionFlags() {
         return mSingleSatCorrectionFlags;
     }
@@ -137,6 +156,7 @@
      * <p>Interpretation depends on {@link #getConstellationType()}. See {@link
      * GnssStatus#getSvid(int)}.
      */
+    @IntRange(from = 0)
     public int getSatelliteId() {
         return mSatId;
     }
@@ -154,6 +174,7 @@
      *
      * @return the carrier frequency of the signal tracked in Hz.
      */
+    @FloatRange(from = 0.0f,  fromInclusive = false)
     public float getCarrierFrequencyHz() {
         return mCarrierFrequencyHz;
     }
@@ -162,7 +183,7 @@
      * Returns the probability that the satellite is in line-of-sight condition at the given
      * location.
      */
-    @FloatRange(from = 0f, to = 1f)
+    @FloatRange(from = 0.0f, to = 1.0f)
     public float getProbabilityLineOfSight() {
         return mProbSatIsLos;
     }
@@ -171,11 +192,13 @@
      * Returns the Excess path length to be subtracted from pseudorange before using it in
      * calculating location.
      */
+    @FloatRange(from = 0.0f)
     public float getExcessPathLengthMeters() {
         return mExcessPathLengthMeters;
     }
 
     /** Returns the error estimate (1-sigma) for the Excess path length estimate */
+    @FloatRange(from = 0.0f)
     public float getExcessPathLengthUncertaintyMeters() {
         return mExcessPathLengthUncertaintyMeters;
     }
@@ -186,7 +209,8 @@
      * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
      * signal goes through multiple reflections or if reflection plane serving is not supported
      */
-    public @Nullable GnssReflectingPlane getReflectingPlane() {
+    @Nullable
+    public GnssReflectingPlane getReflectingPlane() {
         return mReflectingPlane;
     }
 
@@ -215,23 +239,27 @@
         return 0;
     }
 
-    public static final @android.annotation.NonNull Creator<GnssSingleSatCorrection> CREATOR =
+    public static final Creator<GnssSingleSatCorrection> CREATOR =
             new Creator<GnssSingleSatCorrection>() {
                 @Override
-                public GnssSingleSatCorrection createFromParcel(Parcel parcel) {
-                    GnssSingleSatCorrection singleSatCorrection =
+                @NonNull
+                public GnssSingleSatCorrection createFromParcel(@NonNull Parcel parcel) {
+                    int mSingleSatCorrectionFlags = parcel.readInt();
+                    boolean hasReflectingPlane =
+                            (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+                    final GnssSingleSatCorrection.Builder singleSatCorrectionBuilder =
                             new Builder()
-                                    .setSingleSatelliteCorrectionFlags(parcel.readInt())
                                     .setConstellationType(parcel.readInt())
                                     .setSatelliteId(parcel.readInt())
                                     .setCarrierFrequencyHz(parcel.readFloat())
                                     .setProbabilityLineOfSight(parcel.readFloat())
                                     .setExcessPathLengthMeters(parcel.readFloat())
-                                    .setExcessPathLengthUncertaintyMeters(parcel.readFloat())
-                                    .setReflectingPlane(
-                                            GnssReflectingPlane.CREATOR.createFromParcel(parcel))
-                                    .build();
-                    return singleSatCorrection;
+                                    .setExcessPathLengthUncertaintyMeters(parcel.readFloat());
+                    if (hasReflectingPlane) {
+                        singleSatCorrectionBuilder.setReflectingPlane(
+                                GnssReflectingPlane.CREATOR.createFromParcel(parcel));
+                    }
+                    return singleSatCorrectionBuilder.build();
                 }
 
                 @Override
@@ -256,12 +284,14 @@
                         format,
                         "ExcessPathLengthUncertaintyMeters = ",
                         mExcessPathLengthUncertaintyMeters));
-        builder.append(String.format(format, "ReflectingPlane = ", mReflectingPlane));
+        if (hasReflectingPlane()) {
+            builder.append(String.format(format, "ReflectingPlane = ", mReflectingPlane));
+        }
         return builder.toString();
     }
 
     @Override
-    public void writeToParcel(Parcel parcel, int flags) {
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeInt(mSingleSatCorrectionFlags);
         parcel.writeInt(mConstellationType);
         parcel.writeInt(mSatId);
@@ -269,7 +299,9 @@
         parcel.writeFloat(mProbSatIsLos);
         parcel.writeFloat(mExcessPathLengthMeters);
         parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
-        mReflectingPlane.writeToParcel(parcel, flags);
+        if (hasReflectingPlane()) {
+            mReflectingPlane.writeToParcel(parcel, flags);
+        }
     }
 
     /** Builder for {@link GnssSingleSatCorrection} */
@@ -287,28 +319,25 @@
         private float mProbSatIsLos;
         private float mExcessPathLengthMeters;
         private float mExcessPathLengthUncertaintyMeters;
+        @Nullable
         private GnssReflectingPlane mReflectingPlane;
 
-        /** Sets a bitmask of fields present in this object */
-        public Builder setSingleSatelliteCorrectionFlags(int singleSatCorrectionFlags) {
-            mSingleSatCorrectionFlags = singleSatCorrectionFlags;
-            return this;
-        }
-
         /** Sets the constellation type. */
-        public Builder setConstellationType(@GnssStatus.ConstellationType int constellationType) {
+        @NonNull public Builder setConstellationType(
+                @GnssStatus.ConstellationType int constellationType) {
             mConstellationType = constellationType;
             return this;
         }
 
         /** Sets the Satellite ID defined in the ICD of the given constellation. */
-        public Builder setSatelliteId(int satId) {
+        @NonNull public Builder setSatelliteId(@IntRange(from = 0) int satId) {
             mSatId = satId;
             return this;
         }
 
         /** Sets the Carrier frequency in Hz. */
-        public Builder setCarrierFrequencyHz(float carrierFrequencyHz) {
+        @NonNull public Builder setCarrierFrequencyHz(
+                @FloatRange(from = 0.0f,  fromInclusive = false) float carrierFrequencyHz) {
             mCarrierFrequencyHz = carrierFrequencyHz;
             return this;
         }
@@ -317,8 +346,8 @@
          * Sets the line-of-sight probability of the satellite at the given location in the range
          * between 0 and 1.
          */
-        public Builder setProbabilityLineOfSight(
-                @FloatRange(from = 0f, to = 1f) float probSatIsLos) {
+        @NonNull public Builder setProbabilityLineOfSight(
+                @FloatRange(from = 0.0f, to = 1.0f) float probSatIsLos) {
             Preconditions.checkArgumentInRange(
                     probSatIsLos, 0, 1, "probSatIsLos should be between 0 and 1.");
             mProbSatIsLos = probSatIsLos;
@@ -331,7 +360,8 @@
          * Sets the Excess path length to be subtracted from pseudorange before using it in
          * calculating location.
          */
-        public Builder setExcessPathLengthMeters(float excessPathLengthMeters) {
+        @NonNull public Builder setExcessPathLengthMeters(
+                @FloatRange(from = 0.0f) float excessPathLengthMeters) {
             mExcessPathLengthMeters = excessPathLengthMeters;
             mSingleSatCorrectionFlags =
                     (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_MASK);
@@ -339,8 +369,8 @@
         }
 
         /** Sets the error estimate (1-sigma) for the Excess path length estimate */
-        public Builder setExcessPathLengthUncertaintyMeters(
-                float excessPathLengthUncertaintyMeters) {
+        @NonNull public Builder setExcessPathLengthUncertaintyMeters(
+                @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
             mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
             mSingleSatCorrectionFlags =
                     (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_UNC_MASK);
@@ -348,15 +378,20 @@
         }
 
         /** Sets the reflecting plane information */
-        public Builder setReflectingPlane(GnssReflectingPlane reflectingPlane) {
+        @NonNull public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
             mReflectingPlane = reflectingPlane;
-            mSingleSatCorrectionFlags =
-                    (byte) (mSingleSatCorrectionFlags | HAS_REFLECTING_PLANE_MASK);
+            if (reflectingPlane != null) {
+                mSingleSatCorrectionFlags =
+                        (byte) (mSingleSatCorrectionFlags | HAS_REFLECTING_PLANE_MASK);
+            } else {
+                mSingleSatCorrectionFlags =
+                        (byte) (mSingleSatCorrectionFlags & ~HAS_REFLECTING_PLANE_MASK);
+            }
             return this;
         }
 
         /** Builds a {@link GnssSingleSatCorrection} instance as specified by this builder. */
-        public GnssSingleSatCorrection build() {
+        @NonNull public GnssSingleSatCorrection build() {
             return new GnssSingleSatCorrection(this);
         }
     }
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 609a15e..4e37654 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -30,6 +30,7 @@
  * <p>This class is used in conjunction with the {@link Listener} interface.
  *
  * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
+ * @removed
  */
 @Deprecated
 public final class GpsStatus {
@@ -112,6 +113,7 @@
     /**
      * Used for receiving notifications when GPS status has changed.
      * @deprecated use {@link GnssStatus.Callback} instead.
+     * @removed
      */
     @Deprecated
     public interface Listener {
@@ -142,6 +144,7 @@
      * You can implement this interface and call {@link LocationManager#addNmeaListener}
      * to receive NMEA data from the GPS engine.
      * @deprecated use {@link OnNmeaMessageListener} instead.
+     * @removed
      */
     @Deprecated
     public interface NmeaListener {
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 6828c59..db6a4d0 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -44,12 +44,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.location.ProviderProperties;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -78,14 +78,10 @@
     private final GnssMeasurementCallbackTransport mGnssMeasurementCallbackTransport;
     private final GnssNavigationMessageCallbackTransport mGnssNavigationMessageCallbackTransport;
     private final BatchedLocationCallbackTransport mBatchedLocationCallbackTransport;
-    private final HashMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners =
-            new HashMap<>();
-    private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
-            new HashMap<>();
-    private final HashMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners =
-            new HashMap<>();
-    private final HashMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners =
-            new HashMap<>();
+    private final ArrayMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners =
+            new ArrayMap<>();
+    private final ArrayMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+            new ArrayMap<>();
     // volatile + GnssStatus final-fields pattern to avoid a partially published object
     private volatile GnssStatus mGnssStatus;
     private int mTimeToFirstFix;
@@ -170,17 +166,6 @@
     public static final String KEY_LOCATION_CHANGED = "location";
 
     /**
-     * Broadcast intent action indicating that the GPS has either been
-     * enabled or disabled. An intent extra provides this state as a boolean,
-     * where {@code true} means enabled.
-     * @see #EXTRA_GPS_ENABLED
-     *
-     * @hide
-     */
-    public static final String GPS_ENABLED_CHANGE_ACTION =
-        "android.location.GPS_ENABLED_CHANGE";
-
-    /**
      * Broadcast intent action when the set of enabled location providers changes. To check the
      * status of a provider, use {@link #isProviderEnabled(String)}.
      */
@@ -206,26 +191,6 @@
     public static final String MODE_CHANGING_ACTION = "com.android.settings.location.MODE_CHANGING";
 
     /**
-     * Broadcast intent action indicating that the GPS has either started or
-     * stopped receiving GPS fixes. An intent extra provides this state as a
-     * boolean, where {@code true} means that the GPS is actively receiving fixes.
-     * @see #EXTRA_GPS_ENABLED
-     *
-     * @hide
-     */
-    public static final String GPS_FIX_CHANGE_ACTION =
-        "android.location.GPS_FIX_CHANGE";
-
-    /**
-     * The lookup key for a boolean that indicates whether GPS is enabled or
-     * disabled. {@code true} means GPS is enabled. Retrieve it with
-     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_GPS_ENABLED = "enabled";
-
-    /**
      * Broadcast intent action indicating that a high power location requests
      * has either started or stopped being active.  The current state of
      * active location requests should be read from AppOpsManager using
@@ -293,8 +258,7 @@
             "com.android.settings.location.FOOTER_STRING";
 
     // Map from LocationListeners to their associated ListenerTransport objects
-    private final HashMap<LocationListener, ListenerTransport> mListeners =
-        new HashMap<LocationListener,ListenerTransport>();
+    private final ArrayMap<LocationListener, ListenerTransport> mListeners = new ArrayMap<>();
 
     private class ListenerTransport extends ILocationListener.Stub {
         private static final int TYPE_LOCATION_CHANGED = 1;
@@ -405,7 +369,7 @@
      * @hide
      */
     @TestApi
-    public String[] getBackgroundThrottlingWhitelist() {
+    public @NonNull String[] getBackgroundThrottlingWhitelist() {
         try {
             return mService.getBackgroundThrottlingWhitelist();
         } catch (RemoteException e) {
@@ -417,7 +381,7 @@
      * @hide
      */
     @TestApi
-    public String[] getIgnoreSettingsWhitelist() {
+    public @NonNull String[] getIgnoreSettingsWhitelist() {
         try {
             return mService.getIgnoreSettingsWhitelist();
         } catch (RemoteException e) {
@@ -431,7 +395,7 @@
      * right way to create an instance of this class is using the
      * factory Context.getSystemService.
      */
-    public LocationManager(Context context, ILocationManager service) {
+    public LocationManager(@NonNull Context context, @NonNull ILocationManager service) {
         mService = service;
         mContext = context;
         mGnssMeasurementCallbackTransport =
@@ -454,7 +418,7 @@
      *
      * @return list of Strings containing names of the provider
      */
-    public List<String> getAllProviders() {
+    public @NonNull List<String> getAllProviders() {
         try {
             return mService.getAllProviders();
         } catch (RemoteException e) {
@@ -469,7 +433,7 @@
      * enabled are returned.
      * @return list of Strings containing names of the providers
      */
-    public List<String> getProviders(boolean enabledOnly) {
+    public @NonNull List<String> getProviders(boolean enabledOnly) {
         try {
             return mService.getProviders(null, enabledOnly);
         } catch (RemoteException e) {
@@ -488,7 +452,7 @@
      * @throws SecurityException if the caller is not permitted to access the
      * given provider.
      */
-    public LocationProvider getProvider(String name) {
+    public @Nullable LocationProvider getProvider(@NonNull String name) {
         checkProvider(name);
         try {
             ProviderProperties properties = mService.getProviderProperties(name);
@@ -511,7 +475,7 @@
      * enabled are returned.
      * @return list of Strings containing names of the providers
      */
-    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
+    public @NonNull List<String> getProviders(@NonNull Criteria criteria, boolean enabledOnly) {
         checkCriteria(criteria);
         try {
             return mService.getProviders(criteria, enabledOnly);
@@ -542,7 +506,7 @@
      * @param enabledOnly if true then only a provider that is currently enabled is returned
      * @return name of the provider that best matches the requirements
      */
-    public String getBestProvider(Criteria criteria, boolean enabledOnly) {
+    public @Nullable String getBestProvider(@NonNull Criteria criteria, boolean enabledOnly) {
         checkCriteria(criteria);
         try {
             return mService.getBestProvider(criteria, enabledOnly);
@@ -572,8 +536,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(String provider, long minTime, float minDistance,
-            LocationListener listener) {
+    public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance,
+            @NonNull LocationListener listener) {
         checkProvider(provider);
         checkListener(listener);
 
@@ -604,8 +568,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(String provider, long minTime, float minDistance,
-            LocationListener listener, Looper looper) {
+    public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance,
+            @NonNull LocationListener listener, @Nullable Looper looper) {
         checkProvider(provider);
         checkListener(listener);
 
@@ -637,8 +601,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
-            LocationListener listener, Looper looper) {
+    public void requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria,
+            @NonNull LocationListener listener, @Nullable Looper looper) {
         checkCriteria(criteria);
         checkListener(listener);
 
@@ -665,8 +629,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(String provider, long minTime, float minDistance,
-            PendingIntent intent) {
+    public void requestLocationUpdates(@NonNull String provider, long minTime, float minDistance,
+            @NonNull PendingIntent intent) {
         checkProvider(provider);
         checkPendingIntent(intent);
 
@@ -772,8 +736,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
-            PendingIntent intent) {
+    public void requestLocationUpdates(long minTime, float minDistance, @NonNull Criteria criteria,
+            @NonNull PendingIntent intent) {
         checkCriteria(criteria);
         checkPendingIntent(intent);
 
@@ -802,7 +766,8 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
+    public void requestSingleUpdate(
+            @NonNull String provider, @NonNull LocationListener listener, @Nullable Looper looper) {
         checkProvider(provider);
         checkListener(listener);
 
@@ -832,7 +797,10 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
+    public void requestSingleUpdate(
+            @NonNull Criteria criteria,
+            @NonNull LocationListener listener,
+            @Nullable Looper looper) {
         checkCriteria(criteria);
         checkListener(listener);
 
@@ -855,7 +823,7 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(String provider, PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull String provider, @NonNull PendingIntent intent) {
         checkProvider(provider);
         checkPendingIntent(intent);
 
@@ -879,7 +847,7 @@
      * @throws SecurityException if no suitable permission is present
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
+    public void requestSingleUpdate(@NonNull Criteria criteria, @NonNull PendingIntent intent) {
         checkCriteria(criteria);
         checkPendingIntent(intent);
 
@@ -948,8 +916,10 @@
     @SystemApi
     @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(LocationRequest request, LocationListener listener,
-            Looper looper) {
+    public void requestLocationUpdates(
+            @NonNull LocationRequest request,
+            @NonNull LocationListener listener,
+            @Nullable Looper looper) {
         checkListener(listener);
         requestLocationUpdates(request, listener, looper, null);
     }
@@ -978,7 +948,8 @@
     @SystemApi
     @TestApi
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
+    public void requestLocationUpdates(
+            @NonNull LocationRequest request, @NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         requestLocationUpdates(request, null, null, intent);
     }
@@ -1003,7 +974,7 @@
      * @hide
      */
     @RequiresPermission(allOf = {LOCATION_HARDWARE, ACCESS_FINE_LOCATION})
-    public boolean injectLocation(Location newLocation) {
+    public boolean injectLocation(@NonNull Location newLocation) {
         try {
             return mService.injectLocation(newLocation);
         } catch (RemoteException e) {
@@ -1048,7 +1019,7 @@
      * @param listener listener object that no longer needs location updates
      * @throws IllegalArgumentException if listener is null
      */
-    public void removeUpdates(LocationListener listener) {
+    public void removeUpdates(@NonNull LocationListener listener) {
         checkListener(listener);
         String packageName = mContext.getPackageName();
 
@@ -1073,7 +1044,7 @@
      * @param intent pending intent object that no longer needs location updates
      * @throws IllegalArgumentException if intent is null
      */
-    public void removeUpdates(PendingIntent intent) {
+    public void removeUpdates(@NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         String packageName = mContext.getPackageName();
 
@@ -1133,7 +1104,7 @@
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void addProximityAlert(double latitude, double longitude, float radius, long expiration,
-            PendingIntent intent) {
+            @NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         if (expiration < 0) expiration = Long.MAX_VALUE;
 
@@ -1183,7 +1154,10 @@
      * @hide
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public void addGeofence(LocationRequest request, Geofence fence, PendingIntent intent) {
+    public void addGeofence(
+            @NonNull LocationRequest request,
+            @NonNull Geofence fence,
+            @NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         checkGeofence(fence);
 
@@ -1210,7 +1184,7 @@
      * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
      * permission is not present
      */
-    public void removeProximityAlert(PendingIntent intent) {
+    public void removeProximityAlert(@NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         String packageName = mContext.getPackageName();
 
@@ -1237,7 +1211,7 @@
      *
      * @hide
      */
-    public void removeGeofence(Geofence fence, PendingIntent intent) {
+    public void removeGeofence(@NonNull Geofence fence, @NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         checkGeofence(fence);
         String packageName = mContext.getPackageName();
@@ -1260,7 +1234,7 @@
      *
      * @hide
      */
-    public void removeAllGeofences(PendingIntent intent) {
+    public void removeAllGeofences(@NonNull PendingIntent intent) {
         checkPendingIntent(intent);
         String packageName = mContext.getPackageName();
 
@@ -1290,7 +1264,7 @@
      * @hide
      */
     @SystemApi
-    public boolean isLocationEnabledForUser(UserHandle userHandle) {
+    public boolean isLocationEnabledForUser(@NonNull UserHandle userHandle) {
         try {
             return mService.isLocationEnabledForUser(userHandle.getIdentifier());
         } catch (RemoteException e) {
@@ -1309,7 +1283,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(WRITE_SECURE_SETTINGS)
-    public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+    public void setLocationEnabledForUser(boolean enabled, @NonNull UserHandle userHandle) {
         Settings.Secure.putIntForUser(
                 mContext.getContentResolver(),
                 Settings.Secure.LOCATION_MODE,
@@ -1332,7 +1306,7 @@
      *
      * @throws IllegalArgumentException if provider is null
      */
-    public boolean isProviderEnabled(String provider) {
+    public boolean isProviderEnabled(@NonNull String provider) {
         return isProviderEnabledForUser(provider, Process.myUserHandle());
     }
 
@@ -1353,7 +1327,8 @@
      * @hide
      */
     @SystemApi
-    public boolean isProviderEnabledForUser(String provider, UserHandle userHandle) {
+    public boolean isProviderEnabledForUser(
+            @NonNull String provider, @NonNull UserHandle userHandle) {
         checkProvider(provider);
 
         try {
@@ -1382,7 +1357,7 @@
     @SystemApi
     @RequiresPermission(WRITE_SECURE_SETTINGS)
     public boolean setProviderEnabledForUser(
-            String provider, boolean enabled, UserHandle userHandle) {
+            @NonNull String provider, boolean enabled, @NonNull UserHandle userHandle) {
         checkProvider(provider);
 
         return Settings.Secure.setLocationProviderEnabledForUser(
@@ -1406,6 +1381,7 @@
      *
      * @hide
      */
+    @Nullable
     public Location getLastLocation() {
         String packageName = mContext.getPackageName();
 
@@ -1434,7 +1410,8 @@
      * @throws IllegalArgumentException if provider is null or doesn't exist
      */
     @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
-    public Location getLastKnownLocation(String provider) {
+    @Nullable
+    public Location getLastKnownLocation(@NonNull String provider) {
         checkProvider(provider);
         String packageName = mContext.getPackageName();
         LocationRequest request = LocationRequest.createFromDeprecatedProvider(
@@ -1447,10 +1424,6 @@
         }
     }
 
-    // --- Mock provider support ---
-    // TODO: It would be fantastic to deprecate mock providers entirely, and replace
-    // with something closer to LocationProviderBase.java
-
     /**
      * Creates a mock location provider and adds it to the set of active providers.
      *
@@ -1461,7 +1434,8 @@
      * allowed} for your app.
      * @throws IllegalArgumentException if a provider with the given name already exists
      */
-    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
+    public void addTestProvider(
+            @NonNull String name, boolean requiresNetwork, boolean requiresSatellite,
             boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
             boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
         ProviderProperties properties = new ProviderProperties(requiresNetwork,
@@ -1488,7 +1462,7 @@
      * allowed} for your app.
      * @throws IllegalArgumentException if no provider with the given name exists
      */
-    public void removeTestProvider(String provider) {
+    public void removeTestProvider(@NonNull String provider) {
         try {
             mService.removeTestProvider(provider, mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -1512,7 +1486,7 @@
      * @throws IllegalArgumentException if no provider with the given name exists
      * @throws IllegalArgumentException if the location is incomplete
      */
-    public void setTestProviderLocation(String provider, Location loc) {
+    public void setTestProviderLocation(@NonNull String provider, @NonNull Location loc) {
         if (!loc.isComplete()) {
             IllegalArgumentException e = new IllegalArgumentException(
                     "Incomplete location object, missing timestamp or accuracy? " + loc);
@@ -1546,7 +1520,7 @@
      * @deprecated This function has always been a no-op, and may be removed in the future.
      */
     @Deprecated
-    public void clearTestProviderLocation(String provider) {}
+    public void clearTestProviderLocation(@NonNull String provider) {}
 
     /**
      * Sets a mock enabled value for the given provider.  This value will be used in place
@@ -1560,7 +1534,7 @@
      * allowed} for your app.
      * @throws IllegalArgumentException if no provider with the given name exists
      */
-    public void setTestProviderEnabled(String provider, boolean enabled) {
+    public void setTestProviderEnabled(@NonNull String provider, boolean enabled) {
         try {
             mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
         } catch (RemoteException e) {
@@ -1581,7 +1555,7 @@
      * @deprecated Use {@link #setTestProviderEnabled(String, boolean)} instead.
      */
     @Deprecated
-    public void clearTestProviderEnabled(String provider) {
+    public void clearTestProviderEnabled(@NonNull String provider) {
         setTestProviderEnabled(provider, false);
     }
 
@@ -1601,7 +1575,8 @@
      * @deprecated This method has no effect.
      */
     @Deprecated
-    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
+    public void setTestProviderStatus(
+            @NonNull String provider, int status, @Nullable Bundle extras, long updateTime) {
         try {
             mService.setTestProviderStatus(provider, status, extras, updateTime,
                     mContext.getOpPackageName());
@@ -1622,7 +1597,7 @@
      * @deprecated This method has no effect.
      */
     @Deprecated
-    public void clearTestProviderStatus(String provider) {
+    public void clearTestProviderStatus(@NonNull String provider) {
         setTestProviderStatus(provider, LocationProvider.AVAILABLE, null, 0L);
     }
 
@@ -1648,13 +1623,11 @@
     // This class is used to send Gnss status events to the client's specific thread.
     private class GnssStatusListenerTransport extends IGnssStatusListener.Stub {
 
-        private final GpsStatus.Listener mGpsListener;
-        private final GpsStatus.NmeaListener mGpsNmeaListener;
         private final GnssStatus.Callback mGnssCallback;
         private final OnNmeaMessageListener mGnssNmeaListener;
 
         private class GnssHandler extends Handler {
-            public GnssHandler(Handler handler) {
+            GnssHandler(Handler handler) {
                 super(handler != null ? handler.getLooper() : Looper.myLooper());
             }
 
@@ -1663,24 +1636,22 @@
                 switch (msg.what) {
                     case NMEA_RECEIVED:
                         synchronized (mNmeaBuffer) {
-                            int length = mNmeaBuffer.size();
-                            for (int i = 0; i < length; i++) {
-                                Nmea nmea = mNmeaBuffer.get(i);
+                            for (Nmea nmea : mNmeaBuffer) {
                                 mGnssNmeaListener.onNmeaMessage(nmea.mNmea, nmea.mTimestamp);
                             }
                             mNmeaBuffer.clear();
                         }
                         break;
-                    case GpsStatus.GPS_EVENT_STARTED:
+                    case GNSS_EVENT_STARTED:
                         mGnssCallback.onStarted();
                         break;
-                    case GpsStatus.GPS_EVENT_STOPPED:
+                    case GNSS_EVENT_STOPPED:
                         mGnssCallback.onStopped();
                         break;
-                    case GpsStatus.GPS_EVENT_FIRST_FIX:
+                    case GNSS_EVENT_FIRST_FIX:
                         mGnssCallback.onFirstFix(mTimeToFirstFix);
                         break;
-                    case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
+                    case GNSS_EVENT_SATELLITE_STATUS:
                         mGnssCallback.onSatelliteStatusChanged(mGnssStatus);
                         break;
                     default:
@@ -1691,8 +1662,11 @@
 
         private final Handler mGnssHandler;
 
-        // This must not equal any of the GpsStatus event IDs
-        private static final int NMEA_RECEIVED = 1000;
+        private static final int NMEA_RECEIVED = 1;
+        private static final int GNSS_EVENT_STARTED = 2;
+        private static final int GNSS_EVENT_STOPPED = 3;
+        private static final int GNSS_EVENT_FIRST_FIX = 4;
+        private static final int GNSS_EVENT_SATELLITE_STATUS = 5;
 
         private class Nmea {
             long mTimestamp;
@@ -1705,98 +1679,31 @@
         }
         private final ArrayList<Nmea> mNmeaBuffer;
 
-        GnssStatusListenerTransport(GpsStatus.Listener listener) {
-            this(listener, null);
-        }
-
-        GnssStatusListenerTransport(GpsStatus.Listener listener, Handler handler) {
-            mGpsListener = listener;
-            mGnssHandler = new GnssHandler(handler);
-            mGpsNmeaListener = null;
-            mNmeaBuffer = null;
-            mGnssCallback = mGpsListener != null ? new GnssStatus.Callback() {
-                @Override
-                public void onStarted() {
-                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
-                }
-
-                @Override
-                public void onStopped() {
-                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STOPPED);
-                }
-
-                @Override
-                public void onFirstFix(int ttff) {
-                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_FIRST_FIX);
-                }
-
-                @Override
-                public void onSatelliteStatusChanged(GnssStatus status) {
-                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
-                }
-            } : null;
-            mGnssNmeaListener = null;
-        }
-
-        GnssStatusListenerTransport(GpsStatus.NmeaListener listener) {
-            this(listener, null);
-        }
-
-        GnssStatusListenerTransport(GpsStatus.NmeaListener listener, Handler handler) {
-            mGpsListener = null;
-            mGnssHandler = new GnssHandler(handler);
-            mGpsNmeaListener = listener;
-            mNmeaBuffer = new ArrayList<Nmea>();
-            mGnssCallback = null;
-            mGnssNmeaListener = mGpsNmeaListener != null ? new OnNmeaMessageListener() {
-                @Override
-                public void onNmeaMessage(String nmea, long timestamp) {
-                    mGpsNmeaListener.onNmeaReceived(timestamp, nmea);
-                }
-            } : null;
-        }
-
-        GnssStatusListenerTransport(GnssStatus.Callback callback) {
-            this(callback, null);
-        }
-
         GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler) {
             mGnssCallback = callback;
             mGnssHandler = new GnssHandler(handler);
             mGnssNmeaListener = null;
             mNmeaBuffer = null;
-            mGpsListener = null;
-            mGpsNmeaListener = null;
-        }
-
-        GnssStatusListenerTransport(OnNmeaMessageListener listener) {
-            this(listener, null);
         }
 
         GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler) {
             mGnssCallback = null;
             mGnssHandler = new GnssHandler(handler);
             mGnssNmeaListener = listener;
-            mGpsListener = null;
-            mGpsNmeaListener = null;
-            mNmeaBuffer = new ArrayList<Nmea>();
+            mNmeaBuffer = new ArrayList<>();
         }
 
         @Override
         public void onGnssStarted() {
             if (mGnssCallback != null) {
-                Message msg = Message.obtain();
-                msg.what = GpsStatus.GPS_EVENT_STARTED;
-                mGnssHandler.sendMessage(msg);
+                mGnssHandler.obtainMessage(GNSS_EVENT_STARTED).sendToTarget();
             }
         }
 
         @Override
         public void onGnssStopped() {
             if (mGnssCallback != null) {
-                Message msg = Message.obtain();
-                msg.what = GpsStatus.GPS_EVENT_STOPPED;
-                mGnssHandler.sendMessage(msg);
+                mGnssHandler.obtainMessage(GNSS_EVENT_STOPPED).sendToTarget();
             }
         }
 
@@ -1804,9 +1711,7 @@
         public void onFirstFix(int ttff) {
             if (mGnssCallback != null) {
                 mTimeToFirstFix = ttff;
-                Message msg = Message.obtain();
-                msg.what = GpsStatus.GPS_EVENT_FIRST_FIX;
-                mGnssHandler.sendMessage(msg);
+                mGnssHandler.obtainMessage(GNSS_EVENT_FIRST_FIX).sendToTarget();
             }
         }
 
@@ -1817,11 +1722,8 @@
                 mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths,
                         carrierFreqs);
 
-                Message msg = Message.obtain();
-                msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
-                // remove any SV status messages already in the queue
-                mGnssHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
-                mGnssHandler.sendMessage(msg);
+                mGnssHandler.removeMessages(GNSS_EVENT_SATELLITE_STATUS);
+                mGnssHandler.obtainMessage(GNSS_EVENT_SATELLITE_STATUS).sendToTarget();
             }
         }
 
@@ -1831,11 +1733,9 @@
                 synchronized (mNmeaBuffer) {
                     mNmeaBuffer.add(new Nmea(timestamp, nmea));
                 }
-                Message msg = Message.obtain();
-                msg.what = NMEA_RECEIVED;
-                // remove any NMEA_RECEIVED messages already in the queue
+
                 mGnssHandler.removeMessages(NMEA_RECEIVED);
-                mGnssHandler.sendMessage(msg);
+                mGnssHandler.obtainMessage(NMEA_RECEIVED).sendToTarget();
             }
         }
     }
@@ -1849,27 +1749,12 @@
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead.
+     * @removed
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addGpsStatusListener(GpsStatus.Listener listener) {
-        boolean result;
-
-        if (mGpsStatusListeners.get(listener) != null) {
-            // listener is already registered
-            return true;
-        }
-        try {
-            GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener);
-            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
-            if (result) {
-                mGpsStatusListeners.put(listener, transport);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-
-        return result;
+        return false;
     }
 
     /**
@@ -1877,18 +1762,10 @@
      *
      * @param listener GPS status listener object to remove
      * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead.
+     * @removed
      */
     @Deprecated
-    public void removeGpsStatusListener(GpsStatus.Listener listener) {
-        try {
-            GnssStatusListenerTransport transport = mGpsStatusListeners.remove(listener);
-            if (transport != null) {
-                mService.unregisterGnssStatusCallback(transport);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
+    public void removeGpsStatusListener(GpsStatus.Listener listener) {}
 
     /**
      * Registers a GNSS status callback.
@@ -1900,7 +1777,7 @@
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssStatusCallback(GnssStatus.Callback callback) {
+    public boolean registerGnssStatusCallback(@NonNull GnssStatus.Callback callback) {
         return registerGnssStatusCallback(callback, null);
     }
 
@@ -1915,7 +1792,8 @@
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssStatusCallback(GnssStatus.Callback callback, Handler handler) {
+    public boolean registerGnssStatusCallback(
+            @NonNull GnssStatus.Callback callback, @Nullable Handler handler) {
         boolean result;
         if (mGnssStatusListeners.get(callback) != null) {
             // listener is already registered
@@ -1940,7 +1818,7 @@
      *
      * @param callback GNSS status callback object to remove
      */
-    public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
+    public void unregisterGnssStatusCallback(@NonNull GnssStatus.Callback callback) {
         try {
             GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback);
             if (transport != null) {
@@ -1960,27 +1838,12 @@
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      * @deprecated use {@link #addNmeaListener(OnNmeaMessageListener)} instead.
+     * @removed
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
-        boolean result;
-
-        if (mGpsNmeaListeners.get(listener) != null) {
-            // listener is already registered
-            return true;
-        }
-        try {
-            GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener);
-            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
-            if (result) {
-                mGpsNmeaListeners.put(listener, transport);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-
-        return result;
+        return false;
     }
 
     /**
@@ -1988,18 +1851,10 @@
      *
      * @param listener a {@link GpsStatus.NmeaListener} object to remove
      * @deprecated use {@link #removeNmeaListener(OnNmeaMessageListener)} instead.
+     * @removed
      */
     @Deprecated
-    public void removeNmeaListener(GpsStatus.NmeaListener listener) {
-        try {
-            GnssStatusListenerTransport transport = mGpsNmeaListeners.remove(listener);
-            if (transport != null) {
-                mService.unregisterGnssStatusCallback(transport);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
+    public void removeNmeaListener(GpsStatus.NmeaListener listener) {}
 
     /**
      * Adds an NMEA listener.
@@ -2011,7 +1866,7 @@
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean addNmeaListener(OnNmeaMessageListener listener) {
+    public boolean addNmeaListener(@NonNull OnNmeaMessageListener listener) {
         return addNmeaListener(listener, null);
     }
 
@@ -2026,10 +1881,11 @@
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean addNmeaListener(OnNmeaMessageListener listener, Handler handler) {
+    public boolean addNmeaListener(
+            @NonNull OnNmeaMessageListener listener, @Nullable Handler handler) {
         boolean result;
 
-        if (mGpsNmeaListeners.get(listener) != null) {
+        if (mGnssNmeaListeners.get(listener) != null) {
             // listener is already registered
             return true;
         }
@@ -2052,7 +1908,7 @@
      *
      * @param listener a {@link OnNmeaMessageListener} object to remove
      */
-    public void removeNmeaListener(OnNmeaMessageListener listener) {
+    public void removeNmeaListener(@NonNull OnNmeaMessageListener listener) {
         try {
             GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener);
             if (transport != null) {
@@ -2068,6 +1924,7 @@
      * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
      * @hide
      * @deprecated Not supported anymore.
+     * @removed
      */
     @Deprecated
     @SystemApi
@@ -2083,7 +1940,8 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+    public boolean registerGnssMeasurementsCallback(
+            @NonNull GnssMeasurementsEvent.Callback callback) {
         return registerGnssMeasurementsCallback(callback, null);
     }
 
@@ -2095,8 +1953,8 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback,
-            Handler handler) {
+    public boolean registerGnssMeasurementsCallback(
+            @NonNull GnssMeasurementsEvent.Callback callback, @Nullable Handler handler) {
         return mGnssMeasurementCallbackTransport.add(callback, handler);
     }
 
@@ -2120,15 +1978,12 @@
     }
 
     /**
-     * Returns an integer with flags representing the capabilities of the GNSS chipset.
+     * Returns the integer capability flags of the GNSS chipset as defined in {@code
+     * IGnssCallback.hal}
      *
      * @hide
      */
     @SystemApi
-    /**
-     * Returns the integer capability flags of the GNSS chipset as defined in {@code
-     * IGnssCallback.hal}
-     */
     public int getGnssCapabilities() {
         try {
             return mGnssMeasurementCallbackTransport.getGnssCapabilities();
@@ -2144,6 +1999,7 @@
      * @hide
      * @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)}
      *     instead.
+     * @removed
      */
     @Deprecated
     @SystemApi
@@ -2155,7 +2011,8 @@
      *
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
      */
-    public void unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+    public void unregisterGnssMeasurementsCallback(
+            @NonNull GnssMeasurementsEvent.Callback callback) {
         mGnssMeasurementCallbackTransport.remove(callback);
     }
 
@@ -2164,6 +2021,7 @@
      * Don't use it. Use {@link #registerGnssNavigationMessageCallback} instead.
      * @hide
      * @deprecated Not supported anymore.
+     * @removed
      */
     @Deprecated
     @SystemApi
@@ -2179,12 +2037,12 @@
      * @deprecated use
      * {@link #unregisterGnssNavigationMessageCallback(GnssNavigationMessage.Callback)}
      * instead
+     * @removed
      */
     @Deprecated
     @SystemApi
     @SuppressLint("Doclava125")
-    public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
-    }
+    public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {}
 
     /**
      * Registers a GNSS Navigation Message callback.
@@ -2193,7 +2051,7 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     public boolean registerGnssNavigationMessageCallback(
-            GnssNavigationMessage.Callback callback) {
+            @NonNull GnssNavigationMessage.Callback callback) {
         return registerGnssNavigationMessageCallback(callback, null);
     }
 
@@ -2206,7 +2064,7 @@
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean registerGnssNavigationMessageCallback(
-            GnssNavigationMessage.Callback callback, Handler handler) {
+            @NonNull GnssNavigationMessage.Callback callback, @Nullable Handler handler) {
         return mGnssNavigationMessageCallbackTransport.add(callback, handler);
     }
 
@@ -2216,7 +2074,7 @@
      * @param callback a {@link GnssNavigationMessage.Callback} object to remove.
      */
     public void unregisterGnssNavigationMessageCallback(
-            GnssNavigationMessage.Callback callback) {
+            @NonNull GnssNavigationMessage.Callback callback) {
         mGnssNavigationMessageCallbackTransport.remove(callback);
     }
 
@@ -2230,19 +2088,12 @@
      *
      * @param status object containing GPS status details, or null.
      * @return status object containing updated GPS status.
+     * @removed
      */
     @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public GpsStatus getGpsStatus(GpsStatus status) {
-        if (status == null) {
-            status = new GpsStatus();
-        }
-        // When mGnssStatus is null, that means that this method is called outside
-        // onGpsStatusChanged().  Return an empty status to maintain backwards compatibility.
-        if (mGnssStatus != null) {
-            status.setStatus(mGnssStatus, mTimeToFirstFix);
-        }
-        return status;
+    public @Nullable GpsStatus getGpsStatus(@Nullable GpsStatus status) {
+        return null;
     }
 
     /**
@@ -2319,7 +2170,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
     public boolean registerGnssBatchedLocationCallback(long periodNanos, boolean wakeOnFifoFull,
-                                  BatchedLocationCallback callback, Handler handler) {
+            @NonNull BatchedLocationCallback callback, @Nullable Handler handler) {
         mBatchedLocationCallbackTransport.add(callback, handler);
 
         try {
@@ -2357,7 +2208,8 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
-    public boolean unregisterGnssBatchedLocationCallback(BatchedLocationCallback callback) {
+    public boolean unregisterGnssBatchedLocationCallback(
+            @NonNull BatchedLocationCallback callback) {
 
         mBatchedLocationCallbackTransport.remove(callback);
 
@@ -2379,7 +2231,8 @@
      *
      * @return true if the command succeeds.
      */
-    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+    public boolean sendExtraCommand(
+            @NonNull String provider, @NonNull String command, @Nullable Bundle extras) {
         try {
             return mService.sendExtraCommand(provider, command, extras);
         } catch (RemoteException e) {
@@ -2448,7 +2301,7 @@
      * @hide
      */
     @SystemApi
-    public boolean isProviderPackage(String packageName) {
+    public boolean isProviderPackage(@NonNull String packageName) {
         try {
             return mService.isProviderPackage(packageName);
         } catch (RemoteException e) {
@@ -2464,7 +2317,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
-    public void setLocationControllerExtraPackage(String packageName) {
+    public void setLocationControllerExtraPackage(@NonNull String packageName) {
         try {
             mService.setLocationControllerExtraPackage(packageName);
         } catch (RemoteException e) {
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 6fd063e..a05d850 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -17,6 +17,8 @@
 package android.location;
 
 import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -183,14 +185,16 @@
      *
      * @return a new location request
      */
+    @NonNull
     public static LocationRequest create() {
         return new LocationRequest();
     }
 
     /** @hide */
     @SystemApi
-    public static LocationRequest createFromDeprecatedProvider(String provider, long minTime,
-            float minDistance, boolean singleShot) {
+    @NonNull
+    public static LocationRequest createFromDeprecatedProvider(
+            @NonNull String provider, long minTime, float minDistance, boolean singleShot) {
         if (minTime < 0) minTime = 0;
         if (minDistance < 0) minDistance = 0;
 
@@ -215,8 +219,9 @@
 
     /** @hide */
     @SystemApi
-    public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime,
-            float minDistance, boolean singleShot) {
+    @NonNull
+    public static LocationRequest createFromDeprecatedCriteria(
+            @NonNull Criteria criteria, long minTime, float minDistance, boolean singleShot) {
         if (minTime < 0) minTime = 0;
         if (minDistance < 0) minDistance = 0;
 
@@ -287,7 +292,7 @@
      * @return the same object, so that setters can be chained
      * @throws IllegalArgumentException if the quality constant is not valid
      */
-    public LocationRequest setQuality(int quality) {
+    public @NonNull LocationRequest setQuality(int quality) {
         checkQuality(quality);
         mQuality = quality;
         return this;
@@ -330,7 +335,7 @@
      * @return the same object, so that setters can be chained
      * @throws IllegalArgumentException if the interval is less than zero
      */
-    public LocationRequest setInterval(long millis) {
+    public @NonNull LocationRequest setInterval(long millis) {
         checkInterval(millis);
         mInterval = millis;
         if (!mExplicitFastestInterval) {
@@ -362,7 +367,7 @@
      * @hide
      */
     @SystemApi
-    public LocationRequest setLowPowerMode(boolean enabled) {
+    public @NonNull LocationRequest setLowPowerMode(boolean enabled) {
         mLowPowerMode = enabled;
         return this;
     }
@@ -386,7 +391,7 @@
      * @return the same object, so that setters can be chained
      */
     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    public LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) {
+    public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) {
         mLocationSettingsIgnored = locationSettingsIgnored;
         return this;
     }
@@ -427,7 +432,7 @@
      * @return the same object, so that setters can be chained
      * @throws IllegalArgumentException if the interval is less than zero
      */
-    public LocationRequest setFastestInterval(long millis) {
+    public @NonNull LocationRequest setFastestInterval(long millis) {
         checkInterval(millis);
         mExplicitFastestInterval = true;
         mFastestInterval = millis;
@@ -463,7 +468,7 @@
      * @param millis duration of request in milliseconds
      * @return the same object, so that setters can be chained
      */
-    public LocationRequest setExpireIn(long millis) {
+    public @NonNull LocationRequest setExpireIn(long millis) {
         long elapsedRealtime = SystemClock.elapsedRealtime();
 
         // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
@@ -491,7 +496,7 @@
      * @param millis expiration time of request, in milliseconds since boot including suspend
      * @return the same object, so that setters can be chained
      */
-    public LocationRequest setExpireAt(long millis) {
+    public @NonNull LocationRequest setExpireAt(long millis) {
         mExpireAt = millis;
         if (mExpireAt < 0) mExpireAt = 0;
         return this;
@@ -522,7 +527,7 @@
      * @return the same object, so that setters can be chained
      * @throws IllegalArgumentException if numUpdates is 0 or less
      */
-    public LocationRequest setNumUpdates(int numUpdates) {
+    public @NonNull LocationRequest setNumUpdates(int numUpdates) {
         if (numUpdates <= 0) {
             throw new IllegalArgumentException(
                     "invalid numUpdates: " + numUpdates);
@@ -553,7 +558,8 @@
         }
     }
 
-    public LocationRequest setProvider(String provider) {
+    /** Sets the provider to use for this location request. */
+    public @NonNull LocationRequest setProvider(@NonNull String provider) {
         checkProvider(provider);
         mProvider = provider;
         return this;
@@ -561,13 +567,13 @@
 
     /** @hide */
     @SystemApi
-    public String getProvider() {
+    public @NonNull String getProvider() {
         return mProvider;
     }
 
     /** @hide */
     @SystemApi
-    public LocationRequest setSmallestDisplacement(float meters) {
+    public @NonNull LocationRequest setSmallestDisplacement(float meters) {
         checkDisplacement(meters);
         mSmallestDisplacement = meters;
         return this;
@@ -590,13 +596,13 @@
      * @hide
      */
     @SystemApi
-    public void setWorkSource(WorkSource workSource) {
+    public void setWorkSource(@Nullable WorkSource workSource) {
         mWorkSource = workSource;
     }
 
     /** @hide */
     @SystemApi
-    public WorkSource getWorkSource() {
+    public @Nullable WorkSource getWorkSource() {
         return mWorkSource;
     }
 
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 866634e..e5fd0d3 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -118,8 +118,8 @@
     static private boolean mIsHexInput = true;
 
     // End time of emergency call, and extension, if set
-    private long mCallEndElapsedRealtimeMillis = 0;
-    private long mEmergencyExtensionMillis = 0;
+    private volatile long mCallEndElapsedRealtimeMillis = 0;
+    private volatile long mEmergencyExtensionMillis = 0;
 
     public static class GpsNiNotification
     {
@@ -242,8 +242,9 @@
      */
     public boolean getInEmergency() {
         boolean isInEmergencyExtension =
-                (SystemClock.elapsedRealtime() - mCallEndElapsedRealtimeMillis) <
-                        mEmergencyExtensionMillis;
+                (mCallEndElapsedRealtimeMillis > 0)
+                && ((SystemClock.elapsedRealtime() - mCallEndElapsedRealtimeMillis)
+                        < mEmergencyExtensionMillis);
         boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
         return mIsInEmergencyCall || isInEmergencyCallback || isInEmergencyExtension;
     }
diff --git a/media/apex/java/android/media/CallbackDataSourceDesc.java b/media/apex/java/android/media/CallbackDataSourceDesc.java
index cd36414..9209ca9 100644
--- a/media/apex/java/android/media/CallbackDataSourceDesc.java
+++ b/media/apex/java/android/media/CallbackDataSourceDesc.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 /**
  * Structure of data source descriptor for sources using callback.
@@ -37,7 +38,7 @@
      * Return the DataSourceCallback of this data source.
      * @return the DataSourceCallback of this data source
      */
-    public DataSourceCallback getDataSourceCallback() {
+    public @NonNull DataSourceCallback getDataSourceCallback() {
         return mDataSourceCallback;
     }
 
@@ -70,7 +71,7 @@
          * @param dsd the {@link CallbackDataSourceDesc} object whose data will be reused
          * in the new Builder.
          */
-        public Builder(CallbackDataSourceDesc dsd) {
+        public Builder(@Nullable CallbackDataSourceDesc dsd) {
             super(dsd);
             if (dsd == null) {
                 return;  // use default
@@ -86,6 +87,11 @@
          * @return a new {@link CallbackDataSourceDesc} object
          */
         public @NonNull CallbackDataSourceDesc build() {
+            if (mDataSourceCallback == null) {
+                throw new IllegalStateException(
+                        "DataSourceCallback should not be null");
+            }
+
             CallbackDataSourceDesc dsd = new CallbackDataSourceDesc();
             super.build(dsd);
             dsd.mDataSourceCallback = mDataSourceCallback;
diff --git a/media/apex/java/android/media/DataSourceCallback.java b/media/apex/java/android/media/DataSourceCallback.java
index 1afcd20..6515bd6 100644
--- a/media/apex/java/android/media/DataSourceCallback.java
+++ b/media/apex/java/android/media/DataSourceCallback.java
@@ -17,6 +17,8 @@
 
 package android.media;
 
+import android.annotation.NonNull;
+
 import java.io.Closeable;
 import java.io.IOException;
 
@@ -49,7 +51,7 @@
      * @throws IOException on fatal errors.
      * @return the number of bytes read, or -1 if end of stream is reached.
      */
-    public abstract int readAt(long position, byte[] buffer, int offset, int size)
+    public abstract int readAt(long position, @NonNull byte[] buffer, int offset, int size)
             throws IOException;
 
     /**
diff --git a/media/apex/java/android/media/DataSourceDesc.java b/media/apex/java/android/media/DataSourceDesc.java
index 7fc6f79..e6fd120 100644
--- a/media/apex/java/android/media/DataSourceDesc.java
+++ b/media/apex/java/android/media/DataSourceDesc.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 /**
  * Base class of data source descriptor.
@@ -64,7 +65,7 @@
      * Return the media Id of data source.
      * @return the media Id of data source
      */
-    public String getMediaId() {
+    public @Nullable String getMediaId() {
         return mMediaId;
     }
 
@@ -149,7 +150,7 @@
          * @param mediaId the media Id of this data source
          * @return the same Builder instance.
          */
-        public @NonNull T setMediaId(String mediaId) {
+        public @NonNull T setMediaId(@Nullable String mediaId) {
             mMediaId = mediaId;
             return (T) this;
         }
diff --git a/media/apex/java/android/media/FileDataSourceDesc.java b/media/apex/java/android/media/FileDataSourceDesc.java
index e29bd00..4b70367 100644
--- a/media/apex/java/android/media/FileDataSourceDesc.java
+++ b/media/apex/java/android/media/FileDataSourceDesc.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -106,7 +107,7 @@
      * Return the ParcelFileDescriptor of this data source.
      * @return the ParcelFileDescriptor of this data source
      */
-    public ParcelFileDescriptor getParcelFileDescriptor() {
+    public @NonNull ParcelFileDescriptor getParcelFileDescriptor() {
         return mPFD;
     }
 
@@ -159,7 +160,7 @@
          * @param dsd the {@link FileDataSourceDesc} object whose data will be reused
          * in the new Builder.
          */
-        public Builder(FileDataSourceDesc dsd) {
+        public Builder(@Nullable FileDataSourceDesc dsd) {
             super(dsd);
             if (dsd == null) {
                 return;  // use default
diff --git a/media/apex/java/android/media/MediaController2.java b/media/apex/java/android/media/MediaController2.java
index 2709df0..2743a34 100644
--- a/media/apex/java/android/media/MediaController2.java
+++ b/media/apex/java/android/media/MediaController2.java
@@ -181,6 +181,7 @@
      *
      * @return Session2Token of the connected session, or {@code null} if not connected
      */
+    @Nullable
     public Session2Token getConnectedSessionToken() {
         synchronized (mLock) {
             return mConnectedToken;
diff --git a/media/apex/java/android/media/MediaItem2.java b/media/apex/java/android/media/MediaItem2.java
index fc0f08e..ff0d43e 100644
--- a/media/apex/java/android/media/MediaItem2.java
+++ b/media/apex/java/android/media/MediaItem2.java
@@ -245,7 +245,7 @@
     /**
      * Builder for {@link MediaItem2}.
      */
-    public static class Builder {
+    public static final class Builder {
         @SuppressWarnings("WeakerAccess") /* synthetic access */
         MediaMetadata mMetadata;
         @SuppressWarnings("WeakerAccess") /* synthetic access */
diff --git a/media/apex/java/android/media/MediaPlayer2.java b/media/apex/java/android/media/MediaPlayer2.java
index ef30172..f6b2031 100644
--- a/media/apex/java/android/media/MediaPlayer2.java
+++ b/media/apex/java/android/media/MediaPlayer2.java
@@ -344,7 +344,7 @@
      * to free the resources. If not released, too many MediaPlayer2 instances may
      * result in an exception.</p>
      */
-    public MediaPlayer2(Context context) {
+    public MediaPlayer2(@NonNull Context context) {
         mGuard.open("close");
 
         mContext = context;
@@ -488,7 +488,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object play() {
+    public @NonNull Object play() {
         return addTask(new Task(CALL_COMPLETED_PLAY, false) {
             @Override
             void process() {
@@ -508,7 +508,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object prepare() {
+    public @NonNull Object prepare() {
         return addTask(new Task(CALL_COMPLETED_PREPARE, true) {
             @Override
             void process() {
@@ -524,7 +524,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object pause() {
+    public @NonNull Object pause() {
         return addTask(new Task(CALL_COMPLETED_PAUSE, false) {
             @Override
             void process() {
@@ -542,7 +542,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object skipToNext() {
+    public @NonNull Object skipToNext() {
         return addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
             @Override
             void process() {
@@ -700,7 +700,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setAudioAttributes(@NonNull AudioAttributes attributes) {
+    public @NonNull Object setAudioAttributes(@NonNull AudioAttributes attributes) {
         return addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) {
             @Override
             void process() {
@@ -735,7 +735,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setDataSource(@NonNull DataSourceDesc dsd) {
+    public @NonNull Object setDataSource(@NonNull DataSourceDesc dsd) {
         return addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
             @Override
             void process() throws IOException {
@@ -768,7 +768,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setNextDataSource(@NonNull DataSourceDesc dsd) {
+    public @NonNull Object setNextDataSource(@NonNull DataSourceDesc dsd) {
         return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
             @Override
             void process() {
@@ -791,7 +791,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
+    public @NonNull Object setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
         return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) {
             @Override
             void process() {
@@ -853,7 +853,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object clearNextDataSources() {
+    public @NonNull Object clearNextDataSources() {
         return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
             @Override
             void process() {
@@ -1194,7 +1194,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object loopCurrent(boolean loop) {
+    public @NonNull Object loopCurrent(boolean loop) {
         return addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) {
             @Override
             void process() {
@@ -1216,7 +1216,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setPlayerVolume(float volume) {
+    public @NonNull Object setPlayerVolume(float volume) {
         return addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
             @Override
             void process() {
@@ -1257,7 +1257,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object notifyWhenCommandLabelReached(@NonNull Object label) {
+    public @NonNull Object notifyWhenCommandLabelReached(@NonNull Object label) {
         return addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
             @Override
             void process() {
@@ -1285,7 +1285,7 @@
      * @param sh the SurfaceHolder to use for video display
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
-    public Object setDisplay(SurfaceHolder sh) {
+    public @NonNull Object setDisplay(@Nullable SurfaceHolder sh) {
         return addTask(new Task(CALL_COMPLETED_SET_DISPLAY, false) {
             @Override
             void process() {
@@ -1321,7 +1321,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setSurface(Surface surface) {
+    public @NonNull Object setSurface(@Nullable Surface surface) {
         return addTask(new Task(CALL_COMPLETED_SET_SURFACE, false) {
             @Override
             void process() {
@@ -1355,7 +1355,7 @@
      * @see android.os.PowerManager
      */
     // This is an asynchronous call.
-    public Object setWakeLock(@NonNull PowerManager.WakeLock wakeLock) {
+    public @NonNull Object setWakeLock(@NonNull PowerManager.WakeLock wakeLock) {
         return addTask(new Task(CALL_COMPLETED_SET_WAKE_LOCK, false) {
             @Override
             void process() {
@@ -1390,7 +1390,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setScreenOnWhilePlaying(boolean screenOn) {
+    public @NonNull Object setScreenOnWhilePlaying(boolean screenOn) {
         return addTask(new Task(CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING, false) {
             @Override
             void process() {
@@ -1466,7 +1466,7 @@
      */
     // This is a synchronous call.
     @Override
-    public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
+    public boolean setPreferredDevice(@Nullable AudioDeviceInfo deviceInfo) {
         boolean status = native_setPreferredDevice(deviceInfo);
         if (status) {
             synchronized (this) {
@@ -1483,7 +1483,7 @@
      * is not guaranteed to correspond to the actual device being used for playback.
      */
     @Override
-    public AudioDeviceInfo getPreferredDevice() {
+    public @Nullable AudioDeviceInfo getPreferredDevice() {
         synchronized (this) {
             return mPreferredDevice;
         }
@@ -1496,7 +1496,7 @@
      * selected device when the player was last active.
      */
     @Override
-    public native AudioDeviceInfo getRoutedDevice();
+    public @Nullable native AudioDeviceInfo getRoutedDevice();
 
     /**
      * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
@@ -1508,8 +1508,8 @@
      */
     // This is a synchronous call.
     @Override
-    public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
-            Handler handler) {
+    public void addOnRoutingChangedListener(@NonNull AudioRouting.OnRoutingChangedListener listener,
+            @Nullable Handler handler) {
         if (listener == null) {
             throw new IllegalArgumentException("addOnRoutingChangedListener: listener is NULL");
         }
@@ -1527,7 +1527,8 @@
      */
     // This is a synchronous call.
     @Override
-    public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
+    public void removeOnRoutingChangedListener(
+            @NonNull AudioRouting.OnRoutingChangedListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("removeOnRoutingChangedListener: listener is NULL");
         }
@@ -1547,7 +1548,7 @@
      * notification {@code EventCallback.onVideoSizeChanged} when the size
      * is available.
      */
-    public Size getVideoSize() {
+    public @NonNull Size getVideoSize() {
         return mVideoSize;
     }
 
@@ -1560,7 +1561,7 @@
      *
      * Additional vendor-specific fields may also be present in the return value.
      */
-    public PersistableBundle getMetrics() {
+    public @Nullable PersistableBundle getMetrics() {
         PersistableBundle bundle = native_getMetrics();
         return bundle;
     }
@@ -1592,7 +1593,7 @@
      */
     // TODO: make it public when ready
     // This is an asynchronous call.
-    Object setBufferingParams(@NonNull BufferingParams params) {
+    @NonNull Object setBufferingParams(@NonNull BufferingParams params) {
         return addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
             @Override
             void process() {
@@ -1614,7 +1615,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setPlaybackParams(@NonNull PlaybackParams params) {
+    public @NonNull Object setPlaybackParams(@NonNull PlaybackParams params) {
         return addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
             @Override
             void process() {
@@ -1642,7 +1643,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setSyncParams(@NonNull SyncParams params) {
+    public @NonNull Object setSyncParams(@NonNull SyncParams params) {
         return addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
             @Override
             void process() {
@@ -1671,7 +1672,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object seekTo(long msec) {
+    public @NonNull Object seekTo(long msec) {
         return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
     }
 
@@ -1745,7 +1746,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object seekTo(long msec, @SeekMode int mode) {
+    public @NonNull Object seekTo(long msec, @SeekMode int mode) {
         return addTask(new Task(CALL_COMPLETED_SEEK_TO, true) {
             @Override
             void process() {
@@ -1846,7 +1847,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setAudioSessionId(int sessionId) {
+    public @NonNull Object setAudioSessionId(int sessionId) {
         final AudioTrack dummyAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
                     AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 2,
                     AudioTrack.MODE_STATIC, sessionId);
@@ -1887,7 +1888,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object attachAuxEffect(int effectId) {
+    public @NonNull Object attachAuxEffect(int effectId) {
         return addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) {
             @Override
             void process() {
@@ -1912,7 +1913,7 @@
      * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public Object setAuxEffectSendLevel(float level) {
+    public @NonNull Object setAuxEffectSendLevel(float level) {
         return addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) {
             @Override
             void process() {
@@ -1984,7 +1985,7 @@
          * When the language is unknown or could not be determined,
          * ISO-639-2 language code, "und", is returned.
          */
-        public String getLanguage() {
+        public @Nullable String getLanguage() {
             String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
             return language == null ? "und" : language;
         }
@@ -1993,7 +1994,7 @@
          * Gets the {@link MediaFormat} of the track.  If the format is
          * unknown or could not be determined, null is returned.
          */
-        public MediaFormat getFormat() {
+        public @Nullable MediaFormat getFormat() {
             if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
                     || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
                 return mFormat;
@@ -2201,7 +2202,7 @@
      * @see MediaPlayer2#getTrackInfo()
      */
     // This is an asynchronous call.
-    public Object selectTrack(int index) {
+    public @NonNull Object selectTrack(int index) {
         return selectTrack(getCurrentDataSource(), index);
     }
 
@@ -2235,7 +2236,7 @@
      * @see MediaPlayer2#getTrackInfo(DataSourceDesc)
      */
     // This is an asynchronous call.
-    public Object selectTrack(@NonNull DataSourceDesc dsd, int index) {
+    public @NonNull Object selectTrack(@NonNull DataSourceDesc dsd, int index) {
         return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) {
             @Override
             void process() {
@@ -2257,7 +2258,7 @@
      * @see MediaPlayer2#getTrackInfo()
      */
     // This is an asynchronous call.
-    public Object deselectTrack(int index) {
+    public @NonNull Object deselectTrack(int index) {
         return deselectTrack(getCurrentDataSource(), index);
     }
 
@@ -2277,7 +2278,7 @@
      * @see MediaPlayer2#getTrackInfo(DataSourceDesc)
      */
     // This is an asynchronous call.
-    public Object deselectTrack(@NonNull DataSourceDesc dsd, int index) {
+    public @NonNull Object deselectTrack(@NonNull DataSourceDesc dsd, int index) {
         return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) {
             @Override
             void process() {
@@ -2928,7 +2929,7 @@
      * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public void unregisterEventCallback(EventCallback eventCallback) {
+    public void unregisterEventCallback(@NonNull EventCallback eventCallback) {
         synchronized (mEventCbLock) {
             for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
                 if (cb.second == eventCallback) {
@@ -3850,7 +3851,7 @@
      */
     // This is an asynchronous call.
     @TestApi
-    public Object prepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid) {
+    public @NonNull Object prepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid) {
         return addTask(newPrepareDrmTask(dsd, uuid));
     }
 
diff --git a/media/apex/java/android/media/UriDataSourceDesc.java b/media/apex/java/android/media/UriDataSourceDesc.java
index 4eb9e8d..c0b3c82 100644
--- a/media/apex/java/android/media/UriDataSourceDesc.java
+++ b/media/apex/java/android/media/UriDataSourceDesc.java
@@ -51,7 +51,7 @@
      * Return the Uri of this data source.
      * @return the Uri of this data source
      */
-    public Uri getUri() {
+    public @NonNull Uri getUri() {
         return mUri;
     }
 
@@ -59,7 +59,7 @@
      * Return the Uri headers of this data source.
      * @return the Uri headers of this data source
      */
-    public Map<String, String> getHeaders() {
+    public @Nullable Map<String, String> getHeaders() {
         if (mHeader == null) {
             return null;
         }
@@ -70,7 +70,7 @@
      * Return the Uri cookies of this data source.
      * @return the Uri cookies of this data source
      */
-    public List<HttpCookie> getCookies() {
+    public @Nullable List<HttpCookie> getCookies() {
         if (mCookies == null) {
             return null;
         }
@@ -81,7 +81,7 @@
      * Return the Context used for resolving the Uri of this data source.
      * @return the Context used for resolving the Uri of this data source
      */
-    public Context getContext() {
+    public @NonNull Context getContext() {
         return mContext;
     }
 
@@ -117,7 +117,7 @@
          * @param dsd the {@link UriDataSourceDesc} object whose data will be reused
          * in the new Builder.
          */
-        public Builder(UriDataSourceDesc dsd) {
+        public Builder(@Nullable UriDataSourceDesc dsd) {
             super(dsd);
             if (dsd == null) {
                 return;  // use default
@@ -136,6 +136,11 @@
          * @return a new {@link UriDataSourceDesc} object
          */
         public @NonNull UriDataSourceDesc build() {
+            if (mUri == null || mContext == null) {
+                throw new IllegalStateException(
+                        "Uri and Context should not be null");
+            }
+
             UriDataSourceDesc dsd = new UriDataSourceDesc();
             super.build(dsd);
             dsd.mUri = mUri;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 46d4204..c2f29bc 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -374,9 +374,15 @@
      */
     public static final int FLAG_NO_CAPTURE = 0x1 << 10;
 
+    /**
+     * @hide
+     * Flag indicating force muting haptic channels.
+     */
+    public static final int FLAG_MUTE_HAPTIC = 0x1 << 11;
+
     private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
             FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
-            FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER;
+            FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_MUTE_HAPTIC;
     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
 
@@ -467,6 +473,14 @@
     }
 
     /**
+     * Return if haptic channels are muted.
+     * @return {@code true} if haptic channels are muted, {@code false} otherwise.
+     */
+    public boolean areHapticChannelsMuted() {
+        return (mFlags & FLAG_MUTE_HAPTIC) != 0;
+    }
+
+    /**
      * Builder class for {@link AudioAttributes} objects.
      * <p> Here is an example where <code>Builder</code> is used to define the
      * {@link AudioAttributes} to be used by a new <code>AudioTrack</code> instance:
@@ -490,6 +504,7 @@
         private int mContentType = CONTENT_TYPE_UNKNOWN;
         private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
         private int mFlags = 0x0;
+        private boolean mMuteHapticChannels = false;
         private HashSet<String> mTags = new HashSet<String>();
         private Bundle mBundle;
 
@@ -528,6 +543,9 @@
             aa.mUsage = mUsage;
             aa.mSource = mSource;
             aa.mFlags = mFlags;
+            if (mMuteHapticChannels) {
+                aa.mFlags |= FLAG_MUTE_HAPTIC;
+            }
             aa.mTags = (HashSet<String>) mTags.clone();
             aa.mFormattedTags = TextUtils.join(";", mTags);
             if (mBundle != null) {
@@ -630,7 +648,7 @@
          *                     true to allow apps to capture the audio
          * @return the same Builder instance
          */
-        public Builder setAllowCapture(boolean allowCapture) {
+        public @NonNull Builder setAllowCapture(boolean allowCapture) {
             if (allowCapture) {
                 mFlags &= ~FLAG_NO_CAPTURE;
             } else {
@@ -803,6 +821,17 @@
             }
             return this;
         }
+
+        /**
+         * Specifying if haptic should be muted or not when playing audio-haptic coupled data.
+         * By default, haptic channels are enabled.
+         * @param muted true to force muting haptic channels.
+         * @return the same Builder instance.
+         */
+        public Builder setMuteHapticChannels(boolean muted) {
+            mMuteHapticChannels = muted;
+            return this;
+        }
     };
 
     @Override
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 15f9b47..669baea 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4068,6 +4068,10 @@
      /**
      * Indicate Hearing Aid connection state change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+     * This operation is asynchronous but its execution will still be sequentially scheduled
+     * relative to calls to {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+     * * BluetoothDevice, int, int, boolean, int)} and
+     * and {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
      * @param device Bluetooth device connected/disconnected
      * @param state new connection state (BluetoothProfile.STATE_xxx)
      * @param musicDevice Default get system volume for the connecting device.
@@ -4075,27 +4079,27 @@
      * {@link android.bluetooth.BluetoothProfile.HEARING_AID})
      * @param suppressNoisyIntent if true the
      * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
-     * @return a delay in ms that the caller should wait before broadcasting
-     * BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED intent.
      * {@hide}
      */
-    public int setBluetoothHearingAidDeviceConnectionState(
+    public void setBluetoothHearingAidDeviceConnectionState(
                 BluetoothDevice device, int state, boolean suppressNoisyIntent,
                 int musicDevice) {
         final IAudioService service = getService();
-        int delay = 0;
         try {
-            delay = service.setBluetoothHearingAidDeviceConnectionState(device,
+            service.setBluetoothHearingAidDeviceConnectionState(device,
                 state, suppressNoisyIntent, musicDevice);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        return delay;
     }
 
      /**
      * Indicate A2DP source or sink connection state change and eventually suppress
      * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
+     * This operation is asynchronous but its execution will still be sequentially scheduled
+     * relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
+     * int, boolean, int)} and
+     * {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
      * @param device Bluetooth device connected/disconnected
      * @param state  new connection state, {@link BluetoothProfile#STATE_CONNECTED}
      *     or {@link BluetoothProfile#STATE_DISCONNECTED}
@@ -4105,26 +4109,27 @@
      * {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
      * @param suppressNoisyIntent if true the
      * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
-     * @return a delay in ms that the caller should wait before broadcasting
-     * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
      * {@hide}
      */
-    public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+    public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
             BluetoothDevice device, int state,
             int profile, boolean suppressNoisyIntent, int a2dpVolume) {
         final IAudioService service = getService();
-        int delay = 0;
         try {
-            delay = service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
+            service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
                 state, profile, suppressNoisyIntent, a2dpVolume);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        return delay;
     }
 
      /**
      * Indicate A2DP device configuration has changed.
+     * This operation is asynchronous but its execution will still be sequentially scheduled
+     * relative to calls to
+     * {@link #setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice, int, int,
+     * boolean, int)} and
+     * {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice, int, boolean, int)}
      * @param device Bluetooth device whose configuration has changed.
      * {@hide}
      */
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index 9a16aea..333cd2d 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -72,7 +72,7 @@
      *
      * @param audioFormat The format in which to capture the audio.
      */
-    AudioMix createAudioMix(AudioFormat audioFormat) {
+    @NonNull AudioMix createAudioMix(@NonNull AudioFormat audioFormat) {
         return new AudioMix.Builder(mAudioMixingRule)
                 .setFormat(audioFormat)
                 .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER)
@@ -123,7 +123,7 @@
          * @throws IllegalStateException if called in conjunction with
          *     {@link #excludeUsage(AudioAttributes)}.
          */
-        public Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) {
+        public @NonNull Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) {
             Preconditions.checkNotNull(audioAttributes);
             Preconditions.checkState(
                     mUsageMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
@@ -141,7 +141,7 @@
          *
          * @throws IllegalStateException if called in conjunction with {@link #excludeUid(int)}.
          */
-        public Builder addMatchingUid(int uid) {
+        public @NonNull Builder addMatchingUid(int uid) {
             Preconditions.checkState(
                     mUidMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
             mAudioMixingRuleBuilder.addMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
@@ -158,7 +158,7 @@
          * @throws IllegalStateException if called in conjunction with
          *     {@link #addMatchingUsage(AudioAttributes)}.
          */
-        public Builder excludeUsage(@NonNull AudioAttributes audioAttributes) {
+        public @NonNull Builder excludeUsage(@NonNull AudioAttributes audioAttributes) {
             Preconditions.checkNotNull(audioAttributes);
             Preconditions.checkState(
                     mUsageMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
@@ -176,7 +176,7 @@
          *
          * @throws IllegalStateException if called in conjunction with {@link #addMatchingUid(int)}.
          */
-        public Builder excludeUid(int uid) {
+        public @NonNull Builder excludeUid(int uid) {
             Preconditions.checkState(
                     mUidMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
             mAudioMixingRuleBuilder.excludeMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
@@ -189,7 +189,7 @@
          *
          * @throws UnsupportedOperationException if the parameters set are incompatible.
          */
-        public AudioPlaybackCaptureConfiguration build() {
+        public @NonNull AudioPlaybackCaptureConfiguration build() {
             return new AudioPlaybackCaptureConfiguration(mAudioMixingRuleBuilder.build(),
                                                          mProjection);
         }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 3d5120f..28937a6 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -618,7 +618,7 @@
          * @throws IllegalStateException if called in conjunction with {@link #setAudioSource(int)}.
          * @throws NullPointerException if {@code config} is null.
          */
-        public Builder setAudioPlaybackCaptureConfig(
+        public @NonNull Builder setAudioPlaybackCaptureConfig(
                 @NonNull AudioPlaybackCaptureConfiguration config) {
             Preconditions.checkNotNull(
                     config, "Illegal null AudioPlaybackCaptureConfiguration argument");
@@ -647,7 +647,7 @@
             return this;
         }
 
-        private AudioRecord buildAudioPlaybackCaptureRecord() {
+        private @NonNull AudioRecord buildAudioPlaybackCaptureRecord() {
             AudioMix audioMix = mAudioPlaybackCaptureConfiguration.createAudioMix(mFormat);
             MediaProjection projection = mAudioPlaybackCaptureConfiguration.getMediaProjection();
             AudioPolicy audioPolicy = new AudioPolicy.Builder(/*context=*/ null)
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 3bb696b..7cfe0dd 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -3168,7 +3168,8 @@
          * @param sizeInFrames the number of frames available to write without blocking.
          *   Note that the frame size of a compressed stream is 1 byte.
          */
-        public void onDataRequest(@NonNull AudioTrack track, int sizeInFrames) { }
+        public void onDataRequest(@NonNull AudioTrack track, @IntRange(from = 0) int sizeInFrames) {
+        }
     }
 
     /**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 31d2232..bc91ca3 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1891,7 +1891,7 @@
      *
      * @param tag the name of the tag.
      */
-    public boolean hasAttribute(String tag) {
+    public boolean hasAttribute(@NonNull String tag) {
         return (getExifAttribute(tag) != null);
     }
 
diff --git a/media/java/android/media/HwAudioSource.java b/media/java/android/media/HwAudioSource.java
index 8bdb8a6..e53b7e8 100644
--- a/media/java/android/media/HwAudioSource.java
+++ b/media/java/android/media/HwAudioSource.java
@@ -129,6 +129,7 @@
      * Starts the playback from {@link AudioDeviceInfo}.
      */
     public void start() {
+        Preconditions.checkState(!isPlaying(), "HwAudioSource is currently playing");
         baseStart();
         mNativeHandle = AudioSystem.startAudioSource(
                 mAudioDeviceInfo.getPort().activeConfig(),
@@ -136,6 +137,14 @@
     }
 
     /**
+     * Checks whether the HwAudioSource player is playing.
+     * @return true if currently playing, false otherwise
+     */
+    public boolean isPlaying() {
+        return mNativeHandle != 0;
+    }
+
+    /**
      * Stops the playback from {@link AudioDeviceInfo}.
      */
     public void stop() {
@@ -165,7 +174,7 @@
      * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
      * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
      */
-    public static class Builder {
+    public static final class Builder {
         private AudioAttributes mAudioAttributes;
         private AudioDeviceInfo mAudioDeviceInfo;
 
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 1b82fcc..0285667 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -228,10 +228,10 @@
 
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
-    int setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
+    void setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
             int state, boolean suppressNoisyIntent, int musicDevice);
 
-    int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
+    void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
     oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
diff --git a/media/java/android/media/MediaTimestamp.java b/media/java/android/media/MediaTimestamp.java
index 03e454c..da3362a 100644
--- a/media/java/android/media/MediaTimestamp.java
+++ b/media/java/android/media/MediaTimestamp.java
@@ -134,7 +134,7 @@
      * @hide
      */
     @SystemApi
-    public static class Builder {
+    public static final class Builder {
         long mMediaTimeUs;
         long mNanoTime;
         float mClockRate = 1.0f;
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index fbe5152..b302b06 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -571,13 +571,12 @@
     // Utilities
 
     /**
+     * @hide
      * Use to generate warning or exception in legacy code paths that allowed passing stream types
      * to qualify audio playback.
      * @param streamType the stream type to check
      * @throws IllegalArgumentException
-     * @deprecated This method is not intended to be used by applications.
      */
-    @java.lang.Deprecated
     public static void deprecateStreamTypeForPlayback(int streamType, @NonNull String className,
             @NonNull String opName) throws IllegalArgumentException {
         // STREAM_ACCESSIBILITY was introduced at the same time the use of stream types
diff --git a/media/java/android/media/SubtitleData.java b/media/java/android/media/SubtitleData.java
index 852babe..31622a9 100644
--- a/media/java/android/media/SubtitleData.java
+++ b/media/java/android/media/SubtitleData.java
@@ -155,7 +155,7 @@
      * @hide
      */
     @SystemApi
-    public static class Builder {
+    public static final class Builder {
         private int mTrackIndex;
         private long mStartTimeUs;
         private long mDurationUs;
diff --git a/media/java/android/media/TimedMetaData.java b/media/java/android/media/TimedMetaData.java
index 2a89888..990760c 100644
--- a/media/java/android/media/TimedMetaData.java
+++ b/media/java/android/media/TimedMetaData.java
@@ -104,7 +104,7 @@
      * @hide
      */
     @SystemApi
-    public static class Builder {
+    public static final class Builder {
         private long mTimestampUs;
         private byte[] mMetaData = new byte[0];
 
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java
index 98b6d97..c305b68 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategies.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategies.java
@@ -85,7 +85,7 @@
      * Returns an {@link Iterator}
      */
     @Override
-    public Iterator<AudioProductStrategy> iterator() {
+    public @NonNull Iterator<AudioProductStrategy> iterator() {
         return mAudioProductStrategyList.iterator();
     }
 
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
index 0b4ba93..b60947f 100644
--- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
@@ -77,7 +77,7 @@
     /**
      * @return List of {@link AudioAttributes} involved in this {@link AudioVolumeGroup}.
      */
-    public List<AudioAttributes> getAudioAttributes() {
+    public @NonNull List<AudioAttributes> getAudioAttributes() {
         return Arrays.asList(mAudioAttributes);
     }
 
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroups.java b/media/java/android/media/audiopolicy/AudioVolumeGroups.java
index 301bec7..2e56f84 100644
--- a/media/java/android/media/audiopolicy/AudioVolumeGroups.java
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroups.java
@@ -70,7 +70,7 @@
      * Returns an {@link Iterator}
      */
     @Override
-    public Iterator<AudioVolumeGroup> iterator() {
+    public @NonNull Iterator<AudioVolumeGroup> iterator() {
         return mAudioVolumeGroupList.iterator();
     }
 
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index fb473f0..167d255 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -9,7 +9,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     mockito-target-minus-junit4 \
-    android-support-test \
+    androidx.test.rules \
     android-ex-camera2
 
 LOCAL_PACKAGE_NAME := mediaframeworktest
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index e50a375..fb2d630 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -86,7 +86,7 @@
             android:label="MediaFramework integration tests InstrumentationRunner">
     </instrumentation>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.mediaframeworktest"
             android:label="media framework tests">
     </instrumentation>
diff --git a/media/tests/MediaFrameworkTest/AndroidTest.xml b/media/tests/MediaFrameworkTest/AndroidTest.xml
index 204959f..132028c 100644
--- a/media/tests/MediaFrameworkTest/AndroidTest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidTest.xml
@@ -21,7 +21,7 @@
     <option name="test-tag" value="MediaFrameworkTest" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.mediaframeworktest" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index d8c975f..87a59df 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -309,6 +309,10 @@
             Log.v(TAG, String.format("Camera %s has torch status changed to 0x%x",
                     cameraId, status));
         }
+        @Override
+        public void onCameraAccessPrioritiesChanged() {
+            Log.v(TAG, "Camera access permission change");
+        }
     }
 
     /**
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
index feac63d..701454c 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
@@ -28,7 +28,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.mtp.MtpConstants;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.net.MimeUtils;
 
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
index a71977f..bc614e9 100644
--- a/packages/CaptivePortalLogin/Android.bp
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -18,6 +18,7 @@
     name: "CaptivePortalLogin",
     srcs: ["src/**/*.java"],
     sdk_version: "system_current",
+    min_sdk_version: "28",
     certificate: "networkstack",
     static_libs: [
         "androidx.legacy_legacy-support-v4",
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index a5f3b88fe..44e0a65 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -18,7 +18,7 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.captiveportallogin"
-    android:versionCode="10"
+    android:versionCode="11"
     android:versionName="Q-initial">
 
     <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
index 7755cbc..719417e 100644
--- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
+++ b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/DynamicAndroidInstallationService.java
@@ -114,6 +114,7 @@
     private NotificationManager mNM;
 
     private long mSystemSize;
+    private long mUserdataSize;
     private long mInstalledSize;
     private boolean mJustCancelledByUser;
 
@@ -220,9 +221,11 @@
 
         String url = intent.getStringExtra(DynamicAndroidClient.KEY_SYSTEM_URL);
         mSystemSize = intent.getLongExtra(DynamicAndroidClient.KEY_SYSTEM_SIZE, 0);
-        long userdata = intent.getLongExtra(DynamicAndroidClient.KEY_USERDATA_SIZE, 0);
+        mUserdataSize = intent.getLongExtra(DynamicAndroidClient.KEY_USERDATA_SIZE, 0);
 
-        mInstallTask = new InstallationAsyncTask(url, mSystemSize, userdata, mDynAndroid, this);
+        mInstallTask = new InstallationAsyncTask(
+                url, mSystemSize, mUserdataSize, mDynAndroid, this);
+
         mInstallTask.execute();
 
         // start fore ground
@@ -332,8 +335,8 @@
             case STATUS_IN_PROGRESS:
                 builder.setContentText(getString(R.string.notification_install_inprogress));
 
-                int max = (int) Math.max(mSystemSize >> 20, 1);
-                int progress = (int) mInstalledSize >> 20;
+                int max = (int) Math.max((mSystemSize + mUserdataSize) >> 20, 1);
+                int progress = (int) (mInstalledSize >> 20);
 
                 builder.setProgress(max, progress, false);
 
diff --git a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
index 3c759e9..03fc773 100644
--- a/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
+++ b/packages/DynamicAndroidInstallationService/src/com/android/dynandroid/InstallationAsyncTask.java
@@ -16,6 +16,7 @@
 
 package com.android.dynandroid;
 
+import android.gsi.GsiProgress;
 import android.os.AsyncTask;
 import android.os.DynamicAndroidManager;
 import android.util.Log;
@@ -63,8 +64,6 @@
     private final InstallStatusListener mListener;
     private DynamicAndroidManager.Session mInstallationSession;
 
-    private long mInstalledSize;
-    private long mReportedInstalledSize;
     private int mResult = NO_RESULT;
 
     private InputStream mStream;
@@ -89,8 +88,40 @@
         Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
 
         try {
-            // call start in background
-            mInstallationSession = mDynamicAndroid.startInstallation(mSystemSize, mUserdataSize);
+            long installedSize = 0;
+            long reportedInstalledSize = 0;
+
+            long minStepToReport = (mSystemSize + mUserdataSize) / 100;
+
+            // init input stream before calling startInstallation(), which takes 90 seconds.
+            initInputStream();
+
+            Thread thread = new Thread(() -> {
+                mInstallationSession =
+                        mDynamicAndroid.startInstallation(mSystemSize, mUserdataSize);
+            });
+
+
+            thread.start();
+
+            while (thread.isAlive()) {
+                if (isCancelled()) {
+                    boolean aborted = mDynamicAndroid.abort();
+                    Log.d(TAG, "Called DynamicAndroidManager.abort(), result = " + aborted);
+                    return RESULT_OK;
+                }
+
+                GsiProgress progress = mDynamicAndroid.getInstallationProgress();
+                installedSize = progress.bytes_processed;
+
+                if (installedSize > reportedInstalledSize + minStepToReport) {
+                    publishProgress(installedSize);
+                    reportedInstalledSize = installedSize;
+                }
+
+                Thread.sleep(10);
+            }
+
 
             if (mInstallationSession == null) {
                 Log.e(TAG, "Failed to start installation with requested size: "
@@ -99,12 +130,11 @@
                 return RESULT_ERROR_IO;
             }
 
-            initInputStream();
+            installedSize = mUserdataSize;
 
             byte[] bytes = new byte[READ_BUFFER_SIZE];
 
             int numBytesRead;
-            long minStepToReport = mSystemSize / 100;
 
             Log.d(TAG, "Start installation loop");
             while ((numBytesRead = mStream.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
@@ -119,11 +149,11 @@
                     throw new IOException("Failed write() to DynamicAndroid");
                 }
 
-                mInstalledSize += numBytesRead;
+                installedSize += numBytesRead;
 
-                if (mInstalledSize > mReportedInstalledSize + minStepToReport) {
-                    publishProgress(mInstalledSize);
-                    mReportedInstalledSize = mInstalledSize;
+                if (installedSize > reportedInstalledSize + minStepToReport) {
+                    publishProgress(installedSize);
+                    reportedInstalledSize = installedSize;
                 }
             }
 
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index fe6581b..48c72ba 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -25,6 +25,7 @@
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <uses-permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" />
+    <uses-permission android:name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
 
     <application android:label="@string/app_name"
         android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
index eeabb86..293b5b8 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java
@@ -19,6 +19,8 @@
 import static android.ext.services.notification.AssistantSettings.DEFAULT_MAX_SUGGESTIONS;
 import static android.provider.DeviceConfig.setProperty;
 
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
@@ -89,11 +91,11 @@
 
     @Test
     public void testGenerateRepliesDisabled() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -104,11 +106,11 @@
 
     @Test
     public void testGenerateRepliesEnabled() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "true",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -119,11 +121,11 @@
 
     @Test
     public void testGenerateRepliesEmptyFlag() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "false",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -131,11 +133,11 @@
 
         assertFalse(mAssistantSettings.mGenerateReplies);
 
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
                 "",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_REPLIES,
@@ -147,11 +149,11 @@
 
     @Test
     public void testGenerateActionsDisabled() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -162,11 +164,11 @@
 
     @Test
     public void testGenerateActionsEnabled() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "true",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -177,11 +179,11 @@
 
     @Test
     public void testGenerateActionsEmptyFlag() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "false",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -189,11 +191,11 @@
 
         assertFalse(mAssistantSettings.mGenerateActions);
 
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
                 "",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_GENERATE_ACTIONS,
@@ -205,11 +207,11 @@
 
     @Test
     public void testMaxMessagesToExtract() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
                 "10",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_MAX_MESSAGES_TO_EXTRACT,
@@ -220,11 +222,11 @@
 
     @Test
     public void testMaxSuggestions() {
-        setProperty(
+        runWithShellPermissionIdentity(() -> setProperty(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS,
                 "5",
-                false /* makeDefault */);
+                false /* makeDefault */));
         mAssistantSettings.onDeviceConfigPropertyChanged(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.NAS_MAX_SUGGESTIONS,
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 5f1f26d..f210840 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -36,6 +36,7 @@
 android_app {
     name: "NetworkStack",
     sdk_version: "system_current",
+    min_sdk_version: "28",
     certificate: "networkstack",
     privileged: true,
     static_libs: [
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 740c573..003f1e5 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -19,7 +19,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
           android:sharedUserId="android.uid.networkstack"
-          android:versionCode="10"
+          android:versionCode="11"
           android:versionName="Q-initial">
     <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
     <uses-permission android:name="android.permission.INTERNET" />
diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
index 923f162..3dd90ee 100644
--- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java
+++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
@@ -475,7 +475,7 @@
             socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
             SocketAddress addr = makePacketSocketAddress(
                     (short) ETH_P_IPV6, mInterfaceParams.index);
-            SocketUtils.bindSocket(socket, addr);
+            Os.bind(socket, addr);
             SocketUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
         } catch(SocketException|ErrnoException e) {
             Log.e(TAG, "Error starting filter", e);
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index b0e8da9..0b7809e 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -317,7 +317,7 @@
         try {
             mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP);
             SocketAddress addr = makePacketSocketAddress((short) ETH_P_IP, mIface.index);
-            SocketUtils.bindSocket(mPacketSock, addr);
+            Os.bind(mPacketSock, addr);
             SocketUtils.attachDhcpFilter(mPacketSock);
         } catch(SocketException|ErrnoException e) {
             Log.e(TAG, "Error creating packet socket", e);
@@ -412,8 +412,7 @@
         try {
             if (encap == DhcpPacket.ENCAP_L2) {
                 if (DBG) Log.d(TAG, "Broadcasting " + description);
-                SocketUtils.sendTo(
-                        mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
+                Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
             } else if (encap == DhcpPacket.ENCAP_BOOTP && to.equals(INADDR_BROADCAST)) {
                 if (DBG) Log.d(TAG, "Broadcasting " + description);
                 // We only send L3-encapped broadcasts in DhcpRebindingState,
diff --git a/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java b/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
index 649257a..de54824 100644
--- a/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
+++ b/packages/NetworkStack/src/android/net/ip/ConnectivityPacketTracker.java
@@ -104,8 +104,7 @@
             try {
                 s = Os.socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, 0);
                 SocketUtils.attachControlPacketFilter(s, ARPHRD_ETHER);
-                SocketUtils.bindSocket(
-                        s, makePacketSocketAddress((short) ETH_P_ALL, mInterface.index));
+                Os.bind(s, makePacketSocketAddress((short) ETH_P_ALL, mInterface.index));
             } catch (ErrnoException | IOException e) {
                 logError("Failed to create packet tracking socket: ", e);
                 closeFd(s);
diff --git a/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java b/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
index b29d617..6ae9a2b 100644
--- a/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
+++ b/packages/NetworkStack/src/android/net/ip/IpNeighborMonitor.java
@@ -34,7 +34,6 @@
 import android.net.util.NetworkStackUtils;
 import android.net.util.PacketReader;
 import android.net.util.SharedLog;
-import android.net.util.SocketUtils;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -150,7 +149,7 @@
 
         try {
             fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE);
-            SocketUtils.bindSocket(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
+            Os.bind(fd, makeNetlinkSocketAddress(0, OsConstants.RTMGRP_NEIGH));
             NetlinkSocket.connectToKernel(fd);
 
             if (VDBG) {
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index e82a5d7..c3447fd 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -32,6 +32,7 @@
 import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
 import static android.net.metrics.ValidationProbeEvent.PROBE_PRIVDNS;
 import static android.net.util.NetworkStackUtils.isEmpty;
+import static android.provider.Settings.Global.DATA_STALL_EVALUATION_TYPE_DNS;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -128,9 +129,8 @@
     private static final int DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS = 60 * 1000;
     private static final int DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS = 30 * 60 * 1000;
 
-    private static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
     private static final int DEFAULT_DATA_STALL_EVALUATION_TYPES =
-            (1 << DATA_STALL_EVALUATION_TYPE_DNS);
+            DATA_STALL_EVALUATION_TYPE_DNS;
     // Reevaluate it as intending to increase the number. Larger log size may cause statsd
     // log buffer bust and have stats log lost.
     private static final int DEFAULT_DNS_LOG_SIZE = 20;
@@ -1772,7 +1772,7 @@
     }
 
     private boolean dataStallEvaluateTypeEnabled(int type) {
-        return (mDataStallEvaluationType & (1 << type)) != 0;
+        return (mDataStallEvaluationType & type) != 0;
     }
 
     @VisibleForTesting
@@ -1792,7 +1792,7 @@
         }
 
         // Check dns signal. Suspect it may be a data stall if both :
-        // 1. The number of consecutive DNS query timeouts > mConsecutiveDnsTimeoutThreshold.
+        // 1. The number of consecutive DNS query timeouts >= mConsecutiveDnsTimeoutThreshold.
         // 2. Those consecutive DNS queries happened in the last mValidDataStallDnsTimeThreshold ms.
         if (dataStallEvaluateTypeEnabled(DATA_STALL_EVALUATION_TYPE_DNS)) {
             if (mDnsStallDetector.isDataStallSuspected(mConsecutiveDnsTimeoutThreshold,
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 04b906b..ee2baf2 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -20,6 +20,7 @@
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.provider.Settings.Global.DATA_STALL_EVALUATION_TYPE_DNS;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -114,7 +115,6 @@
     private static final String TEST_OTHER_FALLBACK_URL = "http://otherfallback.google.com/gen_204";
     private static final String TEST_MCCMNC = "123456";
 
-    private static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
     private static final int RETURN_CODE_DNS_SUCCESS = 0;
     private static final int RETURN_CODE_DNS_TIMEOUT = 255;
     private static final int DEFAULT_DNS_TIMEOUT_THRESHOLD = 5;
@@ -186,7 +186,7 @@
         when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
 
         setMinDataStallEvaluateInterval(500);
-        setDataStallEvaluationType(1 << DATA_STALL_EVALUATION_TYPE_DNS);
+        setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS);
         setValidDataStallDnsTimeThreshold(500);
         setConsecutiveDnsTimeoutThreshold(5);
     }
diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp
index dd70cf5..8cee92e 100644
--- a/packages/NetworkStackPermissionStub/Android.bp
+++ b/packages/NetworkStackPermissionStub/Android.bp
@@ -21,6 +21,7 @@
     // a classes.dex.
     srcs: ["src/**/*.java"],
     platform_apis: true,
+    min_sdk_version: "28",
     certificate: "networkstack",
     privileged: true,
     manifest: "AndroidManifest.xml",
diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml
index 62bf3de..e83f050 100644
--- a/packages/NetworkStackPermissionStub/AndroidManifest.xml
+++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml
@@ -19,7 +19,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.networkstack.permissionstub"
     android:sharedUserId="android.uid.networkstack"
-    android:versionCode="10"
+    android:versionCode="11"
     android:versionName="Q-initial">
     <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
     <!--
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
index 3ef0235..03dfd3e 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarView.java
@@ -74,6 +74,7 @@
         // For now, we use the bar number as title.
         mBarTitle.setText(Integer.toString(barViewInfo.getHeight()));
         mBarSummary.setText(barViewInfo.getSummary());
+        mIcon.setContentDescription(barViewInfo.getContentDescription());
     }
 
     @VisibleForTesting
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java
index 409f9ea..1ef36a2 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarViewInfo.java
@@ -34,6 +34,7 @@
     private View.OnClickListener mClickListener;
     @StringRes
     private int mSummary;
+    private @Nullable CharSequence mContentDescription;
     // A number indicates this bar's height. The larger number shows a higher bar view.
     private int mHeight;
     // A real height of bar view.
@@ -45,11 +46,14 @@
      * @param icon      The icon of bar view.
      * @param barHeight The height of bar view. Larger number shows a higher bar view.
      * @param summary   The string resource id for summary.
+     * @param contentDescription Optional text that briefly describes the contents of the icon.
      */
-    public BarViewInfo(Drawable icon, @IntRange(from = 0) int barHeight, @StringRes int summary) {
+    public BarViewInfo(Drawable icon, @IntRange(from = 0) int barHeight, @StringRes int summary,
+            @Nullable CharSequence contentDescription) {
         mIcon = icon;
         mHeight = barHeight;
         mSummary = summary;
+        mContentDescription = contentDescription;
     }
 
     /**
@@ -91,6 +95,10 @@
         return mSummary;
     }
 
+    public @Nullable CharSequence getContentDescription() {
+        return mContentDescription;
+    }
+
     void setNormalizedHeight(@IntRange(from = 0) int barHeight) {
         mNormalizedHeight = barHeight;
     }
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote.xml b/packages/SettingsLib/res/drawable/ic_volume_remote.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_volume_remote.xml
rename to packages/SettingsLib/res/drawable/ic_volume_remote.xml
diff --git a/packages/SystemUI/res/drawable/ic_volume_remote_mute.xml b/packages/SettingsLib/res/drawable/ic_volume_remote_mute.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_volume_remote_mute.xml
rename to packages/SettingsLib/res/drawable/ic_volume_remote_mute.xml
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f5d58d8..f4c7275 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -938,7 +938,7 @@
     <!-- [CHAR_LIMIT=60] Label for battery level chart when discharging with duration and using enhanced estimate -->
     <string name="power_discharging_duration_enhanced">About <xliff:g id="time_remaining">%1$s</xliff:g> left based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string>
     <!-- [CHAR_LIMIT=40] Short label for estimated remaining duration of battery charging/discharging -->
-    <string name="power_remaining_duration_only_short"><xliff:g id="time_remaining">%1$s</xliff:g> left</string>
+    <string name="power_remaining_duration_only_short"><xliff:g id="time_remaining">%1$s</xliff:g></string>
 
     <!-- [CHAR_LIMIT=100] Label for enhanced estimated time that phone will run out of battery -->
     <string name="power_discharge_by_enhanced">Should last until about <xliff:g id="time">%1$s</xliff:g> based on your usage (<xliff:g id="level">%2$s</xliff:g>)</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index a6b2410..bee1b3c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -41,6 +41,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
@@ -58,6 +60,8 @@
      */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
+    @VisibleForTesting
+    long mLastUpdateTime;
     private final String mActivityPackage;
     private final String mActivityName;
     private final Intent mIntent;
@@ -157,6 +161,7 @@
      */
     public CharSequence getTitle(Context context) {
         CharSequence title = null;
+        ensureMetadataNotStale(context);
         final PackageManager packageManager = context.getPackageManager();
         if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
             if (mMetaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
@@ -207,6 +212,7 @@
         if (mSummaryOverride != null) {
             return mSummaryOverride;
         }
+        ensureMetadataNotStale(context);
         CharSequence summary = null;
         final PackageManager packageManager = context.getPackageManager();
         if (mMetaData != null) {
@@ -248,6 +254,7 @@
         if (!hasKey()) {
             return null;
         }
+        ensureMetadataNotStale(context);
         if (mMetaData.get(META_DATA_PREFERENCE_KEYHINT) instanceof Integer) {
             return context.getResources().getString(mMetaData.getInt(META_DATA_PREFERENCE_KEYHINT));
         } else {
@@ -268,7 +275,7 @@
         if (context == null || mMetaData == null) {
             return null;
         }
-
+        ensureMetadataNotStale(context);
         int iconResId = mMetaData.getInt(META_DATA_PREFERENCE_ICON);
         // Set the icon
         if (iconResId == 0) {
@@ -294,6 +301,7 @@
                 && mMetaData.containsKey(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE)) {
             return mMetaData.getBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE);
         }
+        ensureMetadataNotStale(context);
         final String pkgName = context.getPackageName();
         // If this drawable is coming from outside Settings, tint it to match the color.
         final ActivityInfo activityInfo = getActivityInfo(context);
@@ -301,6 +309,28 @@
                 && !TextUtils.equals(pkgName, activityInfo.packageName);
     }
 
+    /**
+     * Ensures metadata is not stale for this tile.
+     */
+    private void ensureMetadataNotStale(Context context) {
+        final PackageManager pm = context.getApplicationContext().getPackageManager();
+
+        try {
+            final long lastUpdateTime = pm.getPackageInfo(mActivityPackage,
+                    PackageManager.GET_META_DATA).lastUpdateTime;
+            if (lastUpdateTime == mLastUpdateTime) {
+                // All good. Do nothing
+                return;
+            }
+            // App has been updated since we load metadata last time. Reload metadata.
+            mActivityInfo = null;
+            getActivityInfo(context);
+            mLastUpdateTime = lastUpdateTime;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.d(TAG, "Can't find package, probably uninstalled.");
+        }
+    }
+
     private ActivityInfo getActivityInfo(Context context) {
         if (mActivityInfo == null) {
             final PackageManager pm = context.getApplicationContext().getPackageManager();
@@ -309,6 +339,7 @@
                     pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
             if (infoList != null && !infoList.isEmpty()) {
                 mActivityInfo = infoList.get(0).activityInfo;
+                mMetaData = mActivityInfo.metaData;
             }
         }
         return mActivityInfo;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index 4ac3ce4..09107ce 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -48,6 +48,11 @@
     // Keep last 24 hours of location app information.
     private static final long RECENT_TIME_INTERVAL_MILLIS = DateUtils.DAY_IN_MILLIS;
 
+    /** The flags for querying ops that are trusted for showing in the UI. */
+    public static final int TRUSTED_STATE_FLAGS = AppOpsManager.OP_FLAG_SELF
+            | AppOpsManager.OP_FLAG_UNTRUSTED_PROXY
+            | AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
+
     @VisibleForTesting
     static final int[] LOCATION_OPS = new int[]{
             AppOpsManager.OP_FINE_LOCATION,
@@ -136,8 +141,7 @@
         // Earliest time for a location access to end and still be shown in list.
         long recentLocationCutoffTime = now - RECENT_TIME_INTERVAL_MILLIS;
         for (AppOpsManager.OpEntry entry : entries) {
-            locationAccessFinishTime = Math.max(entry.getLastAccessBackgroundTime(),
-                    entry.getLastAccessForegroundTime());
+            locationAccessFinishTime = entry.getLastAccessTime(TRUSTED_STATE_FLAGS);
         }
         // Bail out if the entry is out of date.
         if (locationAccessFinishTime < recentLocationCutoffTime) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index 43c97df..52d7e2c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -195,19 +195,12 @@
     }
 
     private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
-        // Get the time of day we think device will die rounded to the nearest 15 min.
-        final long roundedTimeOfDayMs =
-                roundTimeToNearestThreshold(
-                        System.currentTimeMillis() + drainTimeMs,
-                        FIFTEEN_MINUTES_MILLIS);
+        // Get the time remaining rounded to the nearest 15 min
+        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, FIFTEEN_MINUTES_MILLIS);
+        CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
+                false /* withSeconds */);
 
-        // convert the time to a properly formatted string.
-        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
-        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
-        Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
-        CharSequence timeString = fmt.format(date);
-
-        return context.getString(R.string.power_discharge_by_only_short, timeString);
+        return context.getString(R.string.power_remaining_duration_only_short, timeString);
     }
 
     public static long convertUsToMs(long timeUs) {
diff --git a/core/java/android/service/textclassifier/ITextLinksCallback.aidl b/packages/SettingsLib/src/com/android/settingslib/volume/D.java
similarity index 65%
rename from core/java/android/service/textclassifier/ITextLinksCallback.aidl
rename to packages/SettingsLib/src/com/android/settingslib/volume/D.java
index a9e0dde..7e0654d 100644
--- a/core/java/android/service/textclassifier/ITextLinksCallback.aidl
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/D.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,15 +14,10 @@
  * limitations under the License.
  */
 
-package android.service.textclassifier;
+package com.android.settingslib.volume;
 
-import android.view.textclassifier.TextLinks;
+import android.util.Log;
 
-/**
- * Callback for a TextLinks request.
- * @hide
- */
-oneway interface ITextLinksCallback {
-    void onSuccess(in TextLinks links);
-    void onFailure();
-}
\ No newline at end of file
+class D {
+    public static boolean BUG = Log.isLoggable("volume", Log.DEBUG);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
similarity index 84%
rename from packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java
rename to packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
index 8b00eee..4ed1154 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/MediaSessions.java
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.volume;
+package com.android.settingslib.volume;
 
 import android.app.PendingIntent;
 import android.content.Context;
@@ -27,7 +27,6 @@
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.MediaController.PlaybackInfo;
-import android.media.session.MediaSession;
 import android.media.session.MediaSession.QueueItem;
 import android.media.session.MediaSession.Token;
 import android.media.session.MediaSessionManager;
@@ -41,7 +40,6 @@
 import android.util.Log;
 
 import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -73,16 +71,24 @@
         mCallbacks = callbacks;
     }
 
+    /**
+     * Dump to {@code writer}
+     */
     public void dump(PrintWriter writer) {
         writer.println(getClass().getSimpleName() + " state:");
-        writer.print("  mInit: "); writer.println(mInit);
-        writer.print("  mRecords.size: "); writer.println(mRecords.size());
+        writer.print("  mInit: ");
+        writer.println(mInit);
+        writer.print("  mRecords.size: ");
+        writer.println(mRecords.size());
         int i = 0;
         for (MediaControllerRecord r : mRecords.values()) {
             dump(++i, writer, r.controller);
         }
     }
 
+    /**
+     * init MediaSessions
+     */
     public void init() {
         if (D.BUG) Log.d(TAG, "init");
         // will throw if no permission
@@ -97,12 +103,18 @@
         mHandler.sendEmptyMessage(H.UPDATE_SESSIONS);
     }
 
+    /**
+     * Destroy MediaSessions
+     */
     public void destroy() {
         if (D.BUG) Log.d(TAG, "destroy");
         mInit = false;
         mMgr.removeOnActiveSessionsChangedListener(mSessionsListener);
     }
 
+    /**
+     * Set volume {@code level} to remote media {@code token}
+     */
     public void setVolume(Token token, int level) {
         final MediaControllerRecord r = mRecords.get(token);
         if (r == null) {
@@ -113,15 +125,17 @@
         r.controller.setVolumeTo(level, 0);
     }
 
-    private void onRemoteVolumeChangedH(MediaSession.Token sessionToken, int flags) {
+    private void onRemoteVolumeChangedH(Token sessionToken, int flags) {
         final MediaController controller = new MediaController(mContext, sessionToken);
-        if (D.BUG) Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " "
-                + Util.audioManagerFlagsToString(flags));
+        if (D.BUG) {
+            Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " "
+                    + Util.audioManagerFlagsToString(flags));
+        }
         final Token token = controller.getSessionToken();
         mCallbacks.onRemoteVolumeChanged(token, flags);
     }
 
-    private void onUpdateRemoteControllerH(MediaSession.Token sessionToken) {
+    private void onUpdateRemoteControllerH(Token sessionToken) {
         final MediaController controller =
                 sessionToken != null ? new MediaController(mContext, sessionToken) : null;
         final String pkg = controller != null ? controller.getPackageName() : null;
@@ -191,7 +205,8 @@
             if (appLabel.length() > 0) {
                 return appLabel;
             }
-        } catch (NameNotFoundException e) { }
+        } catch (NameNotFoundException e) {
+        }
         return pkg;
     }
 
@@ -240,29 +255,11 @@
         }
     }
 
-    public static void dumpMediaSessions(Context context) {
-        final MediaSessionManager mgr = (MediaSessionManager) context
-                .getSystemService(Context.MEDIA_SESSION_SERVICE);
-        try {
-            final List<MediaController> controllers = mgr.getActiveSessions(null);
-            final int N = controllers.size();
-            if (D.BUG) Log.d(TAG, N + " controllers");
-            for (int i = 0; i < N; i++) {
-                final StringWriter sw = new StringWriter();
-                final PrintWriter pw = new PrintWriter(sw, true);
-                dump(i + 1, pw, controllers.get(i));
-                if (D.BUG) Log.d(TAG, sw.toString());
-            }
-        } catch (SecurityException e) {
-            Log.w(TAG, "Not allowed to get sessions", e);
-        }
-    }
-
     private final class MediaControllerRecord extends MediaController.Callback {
-        private final MediaController controller;
+        public final MediaController controller;
 
-        private boolean sentRemote;
-        private String name;
+        public boolean sentRemote;
+        public String name;
 
         private MediaControllerRecord(MediaController controller) {
             this.controller = controller;
@@ -274,8 +271,10 @@
 
         @Override
         public void onAudioInfoChanged(PlaybackInfo info) {
-            if (D.BUG) Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info)
-                    + " sentRemote=" + sentRemote);
+            if (D.BUG) {
+                Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info)
+                        + " sentRemote=" + sentRemote);
+            }
             final boolean remote = isRemote(info);
             if (!remote && sentRemote) {
                 mCallbacks.onRemoteRemoved(controller.getSessionToken());
@@ -324,22 +323,22 @@
 
     private final OnActiveSessionsChangedListener mSessionsListener =
             new OnActiveSessionsChangedListener() {
-        @Override
-        public void onActiveSessionsChanged(List<MediaController> controllers) {
-            onActiveSessionsUpdatedH(controllers);
-        }
-    };
+                @Override
+                public void onActiveSessionsChanged(List<MediaController> controllers) {
+                    onActiveSessionsUpdatedH(controllers);
+                }
+            };
 
     private final IRemoteVolumeController mRvc = new IRemoteVolumeController.Stub() {
         @Override
-        public void remoteVolumeChanged(MediaSession.Token sessionToken, int flags)
+        public void remoteVolumeChanged(Token sessionToken, int flags)
                 throws RemoteException {
             mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0,
                     sessionToken).sendToTarget();
         }
 
         @Override
-        public void updateRemoteController(final MediaSession.Token sessionToken)
+        public void updateRemoteController(final Token sessionToken)
                 throws RemoteException {
             mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, sessionToken).sendToTarget();
         }
@@ -361,18 +360,32 @@
                     onActiveSessionsUpdatedH(mMgr.getActiveSessions(null));
                     break;
                 case REMOTE_VOLUME_CHANGED:
-                    onRemoteVolumeChangedH((MediaSession.Token) msg.obj, msg.arg1);
+                    onRemoteVolumeChangedH((Token) msg.obj, msg.arg1);
                     break;
                 case UPDATE_REMOTE_CONTROLLER:
-                    onUpdateRemoteControllerH((MediaSession.Token) msg.obj);
+                    onUpdateRemoteControllerH((Token) msg.obj);
                     break;
             }
         }
     }
 
+    /**
+     * Callback for remote media sessions
+     */
     public interface Callbacks {
+        /**
+         * Invoked when remote media session is updated
+         */
         void onRemoteUpdate(Token token, String name, PlaybackInfo pi);
+
+        /**
+         * Invoked when remote media session is removed
+         */
         void onRemoteRemoved(Token t);
+
+        /**
+         * Invoked when remote volume is changed
+         */
         void onRemoteVolumeChanged(Token token, int flags);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/Util.java b/packages/SettingsLib/src/com/android/settingslib/volume/Util.java
new file mode 100644
index 0000000..4e770ae
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/Util.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.volume;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.MediaMetadata;
+import android.media.VolumeProvider;
+import android.media.session.MediaController.PlaybackInfo;
+import android.media.session.PlaybackState;
+import android.telephony.TelephonyManager;
+import android.widget.TextView;
+
+import java.util.Objects;
+
+/**
+ * Static helpers for the volume dialog.
+ */
+public class Util {
+
+    private static final int[] AUDIO_MANAGER_FLAGS = new int[]{
+            AudioManager.FLAG_SHOW_UI,
+            AudioManager.FLAG_VIBRATE,
+            AudioManager.FLAG_PLAY_SOUND,
+            AudioManager.FLAG_ALLOW_RINGER_MODES,
+            AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE,
+            AudioManager.FLAG_SHOW_VIBRATE_HINT,
+            AudioManager.FLAG_SHOW_SILENT_HINT,
+            AudioManager.FLAG_FROM_KEY,
+            AudioManager.FLAG_SHOW_UI_WARNINGS,
+    };
+
+    private static final String[] AUDIO_MANAGER_FLAG_NAMES = new String[]{
+            "SHOW_UI",
+            "VIBRATE",
+            "PLAY_SOUND",
+            "ALLOW_RINGER_MODES",
+            "REMOVE_SOUND_AND_VIBRATE",
+            "SHOW_VIBRATE_HINT",
+            "SHOW_SILENT_HINT",
+            "FROM_KEY",
+            "SHOW_UI_WARNINGS",
+    };
+
+    /**
+     * Extract log tag from {@code c}
+     */
+    public static String logTag(Class<?> c) {
+        final String tag = "vol." + c.getSimpleName();
+        return tag.length() < 23 ? tag : tag.substring(0, 23);
+    }
+
+    /**
+     * Convert media metadata to string
+     */
+    public static String mediaMetadataToString(MediaMetadata metadata) {
+        if (metadata == null) return null;
+        return metadata.getDescription().toString();
+    }
+
+    /**
+     * Convert playback info to string
+     */
+    public static String playbackInfoToString(PlaybackInfo info) {
+        if (info == null) return null;
+        final String type = playbackInfoTypeToString(info.getPlaybackType());
+        final String vc = volumeProviderControlToString(info.getVolumeControl());
+        return String.format("PlaybackInfo[vol=%s,max=%s,type=%s,vc=%s],atts=%s",
+                info.getCurrentVolume(), info.getMaxVolume(), type, vc, info.getAudioAttributes());
+    }
+
+    /**
+     * Convert type of playback info to string
+     */
+    public static String playbackInfoTypeToString(int type) {
+        switch (type) {
+            case PlaybackInfo.PLAYBACK_TYPE_LOCAL:
+                return "LOCAL";
+            case PlaybackInfo.PLAYBACK_TYPE_REMOTE:
+                return "REMOTE";
+            default:
+                return "UNKNOWN_" + type;
+        }
+    }
+
+    /**
+     * Convert state of playback info to string
+     */
+    public static String playbackStateStateToString(int state) {
+        switch (state) {
+            case PlaybackState.STATE_NONE:
+                return "STATE_NONE";
+            case PlaybackState.STATE_STOPPED:
+                return "STATE_STOPPED";
+            case PlaybackState.STATE_PAUSED:
+                return "STATE_PAUSED";
+            case PlaybackState.STATE_PLAYING:
+                return "STATE_PLAYING";
+            default:
+                return "UNKNOWN_" + state;
+        }
+    }
+
+    /**
+     * Convert volume provider control to string
+     */
+    public static String volumeProviderControlToString(int control) {
+        switch (control) {
+            case VolumeProvider.VOLUME_CONTROL_ABSOLUTE:
+                return "VOLUME_CONTROL_ABSOLUTE";
+            case VolumeProvider.VOLUME_CONTROL_FIXED:
+                return "VOLUME_CONTROL_FIXED";
+            case VolumeProvider.VOLUME_CONTROL_RELATIVE:
+                return "VOLUME_CONTROL_RELATIVE";
+            default:
+                return "VOLUME_CONTROL_UNKNOWN_" + control;
+        }
+    }
+
+    /**
+     * Convert {@link PlaybackState} to string
+     */
+    public static String playbackStateToString(PlaybackState playbackState) {
+        if (playbackState == null) return null;
+        return playbackStateStateToString(playbackState.getState()) + " " + playbackState;
+    }
+
+    /**
+     * Convert audio manager flags to string
+     */
+    public static String audioManagerFlagsToString(int value) {
+        return bitFieldToString(value, AUDIO_MANAGER_FLAGS, AUDIO_MANAGER_FLAG_NAMES);
+    }
+
+    protected static String bitFieldToString(int value, int[] values, String[] names) {
+        if (value == 0) return "";
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < values.length; i++) {
+            if ((value & values[i]) != 0) {
+                if (sb.length() > 0) sb.append(',');
+                sb.append(names[i]);
+            }
+            value &= ~values[i];
+        }
+        if (value != 0) {
+            if (sb.length() > 0) sb.append(',');
+            sb.append("UNKNOWN_").append(value);
+        }
+        return sb.toString();
+    }
+
+    private static CharSequence emptyToNull(CharSequence str) {
+        return str == null || str.length() == 0 ? null : str;
+    }
+
+    /**
+     * Set text for specific {@link TextView}
+     */
+    public static boolean setText(TextView tv, CharSequence text) {
+        if (Objects.equals(emptyToNull(tv.getText()), emptyToNull(text))) return false;
+        tv.setText(text);
+        return true;
+    }
+
+    /**
+     * Return {@code true} if it is voice capable
+     */
+    public static boolean isVoiceCapable(Context context) {
+        final TelephonyManager telephony =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        return telephony != null && telephony.isVoiceCapable();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 3dd3fb6..4fc62bb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -57,6 +57,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.CollectionUtils;
 import com.android.settingslib.R;
 import com.android.settingslib.utils.ThreadUtils;
 
@@ -133,6 +134,12 @@
     private final ArraySet<ScanResult> mScanResults = new ArraySet<>();
 
     /**
+     * Extra set of unused scan results corresponding to this AccessPoint for verbose logging
+     * purposes, such as a set of Passpoint roaming scan results when home scans are available.
+     */
+    private final ArraySet<ScanResult> mExtraScanResults = new ArraySet<>();
+
+    /**
      * Map of BSSIDs to scored networks for individual bssids.
      *
      * <p>This cache should not be evicted with scan results, as the values here are used to
@@ -216,6 +223,7 @@
      */
     private String mFqdn;
     private String mProviderFriendlyName;
+    private boolean mIsRoaming = false;
 
     private boolean mIsCarrierAp = false;
 
@@ -289,15 +297,12 @@
 
         // Calculate required fields
         updateKey();
-        updateRssi();
+        updateBestRssiInfo();
     }
 
     /**
      * Creates an AccessPoint with only a WifiConfiguration. This is used for the saved networks
      * page.
-     *
-     * Passpoint Credential AccessPoints should be created with this.
-     * Make sure to call setScanResults after constructing with this.
      */
     public AccessPoint(Context context, WifiConfiguration config) {
         mContext = context;
@@ -315,39 +320,33 @@
     }
 
     /**
-     * Initialize an AccessPoint object for a Passpoint OSU Provider.
-     * Make sure to call setScanResults after constructing with this.
+     * Initialize an AccessPoint object for a Passpoint network.
      */
-    public AccessPoint(Context context, OsuProvider provider) {
+    public AccessPoint(@NonNull Context context, @NonNull WifiConfiguration config,
+            @Nullable Collection<ScanResult> homeScans,
+            @Nullable Collection<ScanResult> roamingScans) {
+        mContext = context;
+        networkId = config.networkId;
+        mConfig = config;
+        setScanResultsPasspoint(homeScans, roamingScans);
+        updateKey();
+    }
+
+    /**
+     * Initialize an AccessPoint object for a Passpoint OSU Provider.
+     */
+    public AccessPoint(@NonNull Context context, @NonNull OsuProvider provider,
+            @NonNull Collection<ScanResult> results) {
         mContext = context;
         mOsuProvider = provider;
-        ssid = provider.getFriendlyName();
+        setScanResults(results);
         updateKey();
     }
 
     AccessPoint(Context context, Collection<ScanResult> results) {
         mContext = context;
-
-        if (results.isEmpty()) {
-            throw new IllegalArgumentException("Cannot construct with an empty ScanResult list");
-        }
-        mScanResults.addAll(results);
-
-        // Information derived from scan results
-        ScanResult firstResult = results.iterator().next();
-        ssid = firstResult.SSID;
-        bssid = firstResult.BSSID;
-        security = getSecurity(firstResult);
-        if (security == SECURITY_PSK) {
-            pskType = getPskType(firstResult);
-        }
+        setScanResults(results);
         updateKey();
-        updateRssi();
-
-        // Passpoint Info
-        mIsCarrierAp = firstResult.isCarrierAp;
-        mCarrierApEapType = firstResult.carrierApEapType;
-        mCarrierName = firstResult.carrierName;
     }
 
     @VisibleForTesting void loadConfig(WifiConfiguration config) {
@@ -468,7 +467,8 @@
 
         if (isVerboseLoggingEnabled()) {
             builder.append(",rssi=").append(mRssi);
-            builder.append(",scan cache size=").append(mScanResults.size());
+            builder.append(",scan cache size=").append(mScanResults.size()
+                    + mExtraScanResults.size());
         }
 
         return builder.append(')').toString();
@@ -703,14 +703,19 @@
      *
      * <p>Callers should not modify this set.
      */
-    public Set<ScanResult> getScanResults() { return mScanResults; }
+    public Set<ScanResult> getScanResults() {
+        Set<ScanResult> allScans = new ArraySet<>();
+        allScans.addAll(mScanResults);
+        allScans.addAll(mExtraScanResults);
+        return allScans;
+    }
 
     public Map<String, TimestampedScoredNetwork> getScoredNetworkCache() {
         return mScoredNetworkCache;
     }
 
     /**
-     * Updates {@link #mRssi}.
+     * Updates {@link #mRssi} and sets scan result information to that of the best RSSI scan result.
      *
      * <p>If the given connection is active, the existing value of {@link #mRssi} will be returned.
      * If the given AccessPoint is not active, a value will be calculated from previous scan
@@ -718,22 +723,41 @@
      * value. If the access point is not connected and there are no scan results, the rssi will be
      * set to {@link #UNREACHABLE_RSSI}.
      */
-    private void updateRssi() {
+    private void updateBestRssiInfo() {
         if (this.isActive()) {
             return;
         }
 
-        int rssi = UNREACHABLE_RSSI;
+        ScanResult bestResult = null;
+        int bestRssi = UNREACHABLE_RSSI;
         for (ScanResult result : mScanResults) {
-            if (result.level > rssi) {
-                rssi = result.level;
+            if (result.level > bestRssi) {
+                bestRssi = result.level;
+                bestResult = result;
             }
         }
 
-        if (rssi != UNREACHABLE_RSSI && mRssi != UNREACHABLE_RSSI) {
-            mRssi = (mRssi + rssi) / 2; // half-life previous value
+        // Set the rssi to the average of the current rssi and the previous rssi.
+        if (bestRssi != UNREACHABLE_RSSI && mRssi != UNREACHABLE_RSSI) {
+            mRssi = (mRssi + bestRssi) / 2;
         } else {
-            mRssi = rssi;
+            mRssi = bestRssi;
+        }
+
+        if (bestResult != null) {
+            ssid = bestResult.SSID;
+            bssid = bestResult.BSSID;
+            security = getSecurity(bestResult);
+            if (security == SECURITY_PSK) {
+                pskType = getPskType(bestResult);
+            }
+            mIsCarrierAp = bestResult.isCarrierAp;
+            mCarrierApEapType = bestResult.carrierApEapType;
+            mCarrierName = bestResult.carrierName;
+        }
+        // Update the config SSID of a Passpoint network to that of the best RSSI
+        if (isPasspoint()) {
+            mConfig.SSID = convertToQuotedString(ssid);
         }
     }
 
@@ -897,18 +921,12 @@
                 summary.append(mContext.getString(R.string.tap_to_sign_up));
             }
         } else if (isActive()) {
-            if (isPasspoint()) {
-                // This is the active connection on passpoint
-                summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
-                        /* isEphemeral */ false,
-                        /* suggestionOrSpecifierPackageName */ null));
-            } else if (mConfig != null && getDetailedState() == DetailedState.CONNECTED
+            if (mConfig != null && getDetailedState() == DetailedState.CONNECTED
                     && mIsCarrierAp) {
                 // This is the active connection on a carrier AP
                 summary.append(String.format(mContext.getString(R.string.connected_via_carrier),
                         mCarrierName));
             } else {
-                // This is the active connection on non-passpoint network
                 summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
                         mInfo != null && mInfo.isEphemeral(),
                         mInfo != null ? mInfo.getNetworkSuggestionOrSpecifierPackageName() : null));
@@ -1036,8 +1054,8 @@
     public void startOsuProvisioning() {
         mContext.getSystemService(WifiManager.class).startSubscriptionProvisioning(
                 mOsuProvider,
-                new AccessPointProvisioningCallback(),
-                ThreadUtils.getUiThreadHandler()
+                mContext.getMainExecutor(),
+                new AccessPointProvisioningCallback()
         );
     }
 
@@ -1107,7 +1125,8 @@
         if (mConfig != null) savedState.putParcelable(KEY_CONFIG, mConfig);
         savedState.putParcelable(KEY_WIFIINFO, mInfo);
         savedState.putParcelableArray(KEY_SCANRESULTS,
-                mScanResults.toArray(new Parcelable[mScanResults.size()]));
+                mScanResults.toArray(new Parcelable[mScanResults.size()
+                        + mExtraScanResults.size()]));
         savedState.putParcelableArrayList(KEY_SCOREDNETWORKCACHE,
                 new ArrayList<>(mScoredNetworkCache.values()));
         if (mNetworkInfo != null) {
@@ -1129,24 +1148,27 @@
     }
 
     /**
-     * Sets {@link #mScanResults} to the given collection.
+     * Sets {@link #mScanResults} to the given collection and updates info based on the best RSSI
+     * scan result.
      *
      * @param scanResults a collection of scan results to add to the internal set
-     * @throws IllegalArgumentException if any of the given ScanResults did not belong to this AP
      */
     void setScanResults(Collection<ScanResult> scanResults) {
+        if (CollectionUtils.isEmpty(scanResults)) {
+            Log.d(TAG, "Cannot set scan results to empty list");
+            return;
+        }
 
         // Validate scan results are for current AP only by matching SSID/BSSID
         // Passpoint networks are not bound to a specific SSID/BSSID, so skip this for passpoint.
-        if (!isPasspoint() && !isOsuProvider()) {
-            String key = getKey();
+        if (mKey != null && !isPasspoint() && !isOsuProvider()) {
             for (ScanResult result : scanResults) {
                 String scanResultKey = AccessPoint.getKey(result);
-                if (!mKey.equals(scanResultKey)) {
-                    throw new IllegalArgumentException(
-                            String.format(
+                if (mKey != null && !mKey.equals(scanResultKey)) {
+                    Log.d(TAG, String.format(
                                     "ScanResult %s\nkey of %s did not match current AP key %s",
-                                    result, scanResultKey, key));
+                                    result, scanResultKey, mKey));
+                    return;
                 }
             }
         }
@@ -1154,7 +1176,7 @@
         int oldLevel = getLevel();
         mScanResults.clear();
         mScanResults.addAll(scanResults);
-        updateRssi();
+        updateBestRssiInfo();
         int newLevel = getLevel();
 
         // If newLevel is 0, there will be no displayed Preference since the AP is unreachable
@@ -1174,20 +1196,26 @@
                 mAccessPointListener.onAccessPointChanged(this);
             }
         });
+    }
 
-        if (!scanResults.isEmpty()) {
-            ScanResult result = scanResults.iterator().next();
-
-            // This flag only comes from scans, is not easily saved in config
-            if (security == SECURITY_PSK) {
-                pskType = getPskType(result);
+    /**
+     * Sets the internal scan result cache to the list of home scans.
+     * If there are no home scans, then the roaming scan list is used, and the AccessPoint is
+     * marked as roaming.
+     */
+    void setScanResultsPasspoint(
+            @Nullable Collection<ScanResult> homeScans,
+            @Nullable Collection<ScanResult> roamingScans) {
+        mExtraScanResults.clear();
+        if (!CollectionUtils.isEmpty(homeScans)) {
+            if (!CollectionUtils.isEmpty(roamingScans)) {
+                mExtraScanResults.addAll(roamingScans);
             }
-
-            // The carrier info in the ScanResult is set by the platform based on the SSID and will
-            // always be the same for all matching scan results.
-            mIsCarrierAp = result.isCarrierAp;
-            mCarrierApEapType = result.carrierApEapType;
-            mCarrierName = result.carrierName;
+            mIsRoaming = false;
+            setScanResults(homeScans);
+        } else if (!CollectionUtils.isEmpty(roamingScans)) {
+            mIsRoaming = true;
+            setScanResults(roamingScans);
         }
     }
 
@@ -1204,7 +1232,6 @@
      */
     public boolean update(
             @Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
-
         boolean updated = false;
         final int oldLevel = getLevel();
         if (info != null && isInfoForThisAccessPoint(config, info)) {
@@ -1538,7 +1565,8 @@
      *
      * All methods are invoked on the Main Thread
      */
-    private class AccessPointProvisioningCallback extends ProvisioningCallback {
+    @VisibleForTesting
+    class AccessPointProvisioningCallback extends ProvisioningCallback {
         @Override
         @MainThread public void onProvisioningFailure(int status) {
             if (TextUtils.equals(mOsuStatus, mContext.getString(R.string.osu_completing_sign_up))) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 871e248..3c10688 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -117,7 +117,11 @@
             if (connected) {
                 mWifiInfo = mWifiManager.getConnectionInfo();
                 if (mWifiInfo != null) {
-                    ssid = getValidSsid(mWifiInfo);
+                    if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
+                        ssid = mWifiInfo.getProviderFriendlyName();
+                    } else {
+                        ssid = getValidSsid(mWifiInfo);
+                    }
                     updateRssi(mWifiInfo.getRssi());
                     maybeRequestNetworkScore();
                 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 9ce6b34..a31d64c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -53,7 +53,6 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.util.CollectionUtils;
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -646,30 +645,14 @@
                 Map<Integer, List<ScanResult>>> pairing : passpointConfigsAndScans) {
             WifiConfiguration config = pairing.first;
             if (seenFQDNs.add(config.FQDN)) {
-                List<ScanResult> apScanResults = new ArrayList<>();
-
                 List<ScanResult> homeScans =
                         pairing.second.get(WifiManager.PASSPOINT_HOME_NETWORK);
                 List<ScanResult> roamingScans =
                         pairing.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK);
 
-                // TODO(b/118705403): Differentiate home network vs roaming network for summary info
-                if (!CollectionUtils.isEmpty(homeScans)) {
-                    apScanResults.addAll(homeScans);
-                } else if (!CollectionUtils.isEmpty(roamingScans)) {
-                    apScanResults.addAll(roamingScans);
-                }
-
-                int bestRssi = Integer.MIN_VALUE;
-                for (ScanResult result : apScanResults) {
-                    if (result.level >= bestRssi) {
-                        bestRssi = result.level;
-                        config.SSID = AccessPoint.convertToQuotedString(result.SSID);
-                    }
-                }
-
                 AccessPoint accessPoint =
-                        getCachedOrCreatePasspoint(apScanResults, accessPointCache, config);
+                        getCachedOrCreatePasspoint(config, homeScans, roamingScans,
+                                accessPointCache);
                 accessPoints.add(accessPoint);
             }
         }
@@ -688,8 +671,8 @@
         for (OsuProvider provider : providersAndScans.keySet()) {
             if (!alreadyProvisioned.contains(provider)) {
                 AccessPoint accessPointOsu =
-                        getCachedOrCreateOsu(providersAndScans.get(provider),
-                                accessPointCache, provider);
+                        getCachedOrCreateOsu(provider, providersAndScans.get(provider),
+                                accessPointCache);
                 accessPoints.add(accessPointOsu);
             }
         }
@@ -709,26 +692,29 @@
     }
 
     private AccessPoint getCachedOrCreatePasspoint(
-            List<ScanResult> scanResults,
-            List<AccessPoint> cache,
-            WifiConfiguration config) {
+            WifiConfiguration config,
+            List<ScanResult> homeScans,
+            List<ScanResult> roamingScans,
+            List<AccessPoint> cache) {
         AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(config));
         if (accessPoint == null) {
-            accessPoint = new AccessPoint(mContext, config);
+            accessPoint = new AccessPoint(mContext, config, homeScans, roamingScans);
+        } else {
+            accessPoint.setScanResultsPasspoint(homeScans, roamingScans);
         }
-        accessPoint.setScanResults(scanResults);
         return accessPoint;
     }
 
     private AccessPoint getCachedOrCreateOsu(
+            OsuProvider provider,
             List<ScanResult> scanResults,
-            List<AccessPoint> cache,
-            OsuProvider provider) {
+            List<AccessPoint> cache) {
         AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(provider));
         if (accessPoint == null) {
-            accessPoint = new AccessPoint(mContext, provider);
+            accessPoint = new AccessPoint(mContext, provider, scanResults);
+        } else {
+            accessPoint.setScanResults(scanResults);
         }
-        accessPoint.setScanResults(scanResults);
         return accessPoint;
     }
 
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index f5ead0c..06f5fde 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -43,13 +43,16 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.WifiSsid;
+import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.net.wifi.hotspot2.pps.HomeSp;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.text.SpannableString;
 import android.text.format.DateUtils;
+import android.util.ArraySet;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -68,6 +71,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
 @SmallTest
@@ -75,8 +81,11 @@
 public class AccessPointTest {
 
     private static final String TEST_SSID = "\"test_ssid\"";
+    private static final String ROAMING_SSID = "\"roaming_ssid\"";
+    private static final String OSU_FRIENDLY_NAME = "osu_friendly_name";
 
-    private static final ArrayList<ScanResult> SCAN_RESULTS = buildScanResultCache();
+    private ArrayList<ScanResult> mScanResults;
+    private ArrayList<ScanResult> mRoamingScans;
 
     private static final RssiCurve FAST_BADGE_CURVE =
             new RssiCurve(-150, 10, new byte[]{Speed.FAST});
@@ -88,10 +97,11 @@
     private WifiInfo mWifiInfo;
     @Mock private RssiCurve mockBadgeCurve;
     @Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
-    public static final int NETWORK_ID = 123;
-    public static final int DEFAULT_RSSI = -55;
+    @Mock private AccessPoint.AccessPointListener mMockAccessPointListener;
+    private static final int NETWORK_ID = 123;
+    private static final int DEFAULT_RSSI = -55;
 
-    private static ScanResult createScanResult(String ssid, String bssid, int rssi) {
+    private ScanResult createScanResult(String ssid, String bssid, int rssi) {
         ScanResult scanResult = new ScanResult();
         scanResult.SSID = ssid;
         scanResult.level = rssi;
@@ -101,6 +111,12 @@
         return scanResult;
     }
 
+    private OsuProvider createOsuProvider() {
+        Map<String, String> friendlyNames = new HashMap<>();
+        friendlyNames.put("en", OSU_FRIENDLY_NAME);
+        return new OsuProvider(null, friendlyNames, null, null, null, null, null);
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -108,6 +124,8 @@
         mWifiInfo = new WifiInfo();
         mWifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
         mWifiInfo.setBSSID(TEST_BSSID);
+        mScanResults = buildScanResultCache(TEST_SSID);
+        mRoamingScans = buildScanResultCache(ROAMING_SSID);
         WifiTracker.sVerboseLogging = false;
     }
 
@@ -573,14 +591,14 @@
         Bundle bundle = new Bundle();
         bundle.putParcelableArray(
                 AccessPoint.KEY_SCANRESULTS,
-                SCAN_RESULTS.toArray(new Parcelable[SCAN_RESULTS.size()]));
+                mScanResults.toArray(new Parcelable[mScanResults.size()]));
         return new AccessPoint(mContext, bundle);
     }
 
-    private static ArrayList<ScanResult> buildScanResultCache() {
+    private ArrayList<ScanResult> buildScanResultCache(String ssid) {
         ArrayList<ScanResult> scanResults = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
-            ScanResult scanResult = createScanResult(TEST_SSID, "bssid-" + i, i);
+            ScanResult scanResult = createScanResult(ssid, "bssid-" + i, i);
             scanResults.add(scanResult);
         }
         return scanResults;
@@ -975,12 +993,12 @@
         int speed1 = Speed.MODERATE;
         RssiCurve badgeCurve1 = mock(RssiCurve.class);
         when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1);
-        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0)))
+        when(mockWifiNetworkScoreCache.getScoredNetwork(mScanResults.get(0)))
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1));
         int speed2 = Speed.VERY_FAST;
         RssiCurve badgeCurve2 = mock(RssiCurve.class);
         when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2);
-        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1)))
+        when(mockWifiNetworkScoreCache.getScoredNetwork(mScanResults.get(1)))
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
 
         int expectedSpeed = (speed1 + speed2) / 2;
@@ -998,12 +1016,12 @@
         int speed1 = Speed.VERY_FAST;
         RssiCurve badgeCurve1 = mock(RssiCurve.class);
         when(badgeCurve1.lookupScore(anyInt())).thenReturn((byte) speed1);
-        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(0)))
+        when(mockWifiNetworkScoreCache.getScoredNetwork(mScanResults.get(0)))
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve1));
         int speed2 = Speed.NONE;
         RssiCurve badgeCurve2 = mock(RssiCurve.class);
         when(badgeCurve2.lookupScore(anyInt())).thenReturn((byte) speed2);
-        when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1)))
+        when(mockWifiNetworkScoreCache.getScoredNetwork(mScanResults.get(1)))
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
 
         ap.update(
@@ -1123,7 +1141,7 @@
                 .setActive(true)
                 .setScoredNetworkCache(
                         new ArrayList(Arrays.asList(recentScore)))
-                .setScanResults(SCAN_RESULTS)
+                .setScanResults(mScanResults)
                 .build();
 
         when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
@@ -1151,7 +1169,7 @@
                 .setActive(true)
                 .setScoredNetworkCache(
                         new ArrayList(Arrays.asList(recentScore)))
-                .setScanResults(SCAN_RESULTS)
+                .setScanResults(mScanResults)
                 .build();
 
         int newSpeed = Speed.MODERATE;
@@ -1196,7 +1214,7 @@
         AccessPoint ap = new TestAccessPointBuilder(mContext)
                 .setSsid(TEST_SSID)
                 .setBssid(TEST_BSSID)
-                .setScanResults(SCAN_RESULTS)
+                .setScanResults(mScanResults)
                 .build();
 
         assertThat(ap.update(null, mWifiInfo, null)).isFalse();
@@ -1217,4 +1235,172 @@
 
         assertThat(passpointAp.update(null, mWifiInfo, null)).isFalse();
     }
+
+    /**
+     * Verifies that an AccessPoint's getKey() is consistent with the overloaded static getKey().
+     */
+    @Test
+    public void testGetKey_matchesKeysCorrectly() {
+        AccessPoint ap = new AccessPoint(mContext, mScanResults);
+        assertThat(ap.getKey()).isEqualTo(AccessPoint.getKey(mScanResults.get(0)));
+
+        WifiConfiguration spyConfig = spy(new WifiConfiguration());
+        when(spyConfig.isPasspoint()).thenReturn(true);
+        spyConfig.FQDN = "fqdn";
+        AccessPoint passpointAp = new AccessPoint(mContext, spyConfig, mScanResults, null);
+        assertThat(passpointAp.getKey()).isEqualTo(AccessPoint.getKey(spyConfig));
+
+        OsuProvider provider = createOsuProvider();
+        AccessPoint osuAp = new AccessPoint(mContext, provider, mScanResults);
+        assertThat(osuAp.getKey()).isEqualTo(AccessPoint.getKey(provider));
+    }
+
+    /**
+     * Verifies that the Passpoint AccessPoint constructor creates AccessPoints whose isPasspoint()
+     * returns true.
+     */
+    @Test
+    public void testPasspointAccessPointConstructor_createdAccessPointIsPasspoint() {
+        WifiConfiguration spyConfig = spy(new WifiConfiguration());
+        when(spyConfig.isPasspoint()).thenReturn(true);
+        AccessPoint passpointAccessPoint = new AccessPoint(mContext, spyConfig,
+                mScanResults, mRoamingScans);
+
+        assertThat(passpointAccessPoint.isPasspoint()).isTrue();
+    }
+
+    /**
+     * Verifies that Passpoint AccessPoints set their config's SSID to the home scans', and to the
+     * roaming scans' if no home scans are available.
+     */
+    @Test
+    public void testSetScanResultsPasspoint_differentiatesHomeAndRoaming() {
+        WifiConfiguration spyConfig = spy(new WifiConfiguration());
+        when(spyConfig.isPasspoint()).thenReturn(true);
+        AccessPoint passpointAccessPoint = new AccessPoint(mContext, spyConfig,
+                mScanResults, mRoamingScans);
+        assertThat(AccessPoint.removeDoubleQuotes(spyConfig.SSID)).isEqualTo(TEST_SSID);
+
+        passpointAccessPoint.setScanResultsPasspoint(null, mRoamingScans);
+        assertThat(AccessPoint.removeDoubleQuotes(spyConfig.SSID)).isEqualTo(ROAMING_SSID);
+
+        passpointAccessPoint.setScanResultsPasspoint(mScanResults, null);
+        assertThat(AccessPoint.removeDoubleQuotes(spyConfig.SSID)).isEqualTo(TEST_SSID);
+    }
+
+    /**
+     * Verifies that getScanResults returns both home and roaming scans.
+     */
+    @Test
+    public void testGetScanResults_showsHomeAndRoamingScans() {
+        WifiConfiguration spyConfig = spy(new WifiConfiguration());
+        when(spyConfig.isPasspoint()).thenReturn(true);
+        AccessPoint passpointAccessPoint = new AccessPoint(mContext, spyConfig,
+                mScanResults, mRoamingScans);
+        Set<ScanResult> fullSet = new ArraySet<>();
+        fullSet.addAll(mScanResults);
+        fullSet.addAll(mRoamingScans);
+        assertThat(passpointAccessPoint.getScanResults()).isEqualTo(fullSet);
+    }
+
+    /**
+     * Verifies that the Passpoint AccessPoint takes the ssid of the strongest scan result.
+     */
+    @Test
+    public void testPasspointAccessPoint_setsBestSsid() {
+        WifiConfiguration spyConfig = spy(new WifiConfiguration());
+        when(spyConfig.isPasspoint()).thenReturn(true);
+
+        String badSsid = "badSsid";
+        String goodSsid = "goodSsid";
+        String bestSsid = "bestSsid";
+        ScanResult badScanResult = createScanResult(badSsid, TEST_BSSID, -100);
+        ScanResult goodScanResult = createScanResult(goodSsid, TEST_BSSID, -10);
+        ScanResult bestScanResult = createScanResult(bestSsid, TEST_BSSID, -1);
+
+        AccessPoint passpointAccessPoint = new AccessPoint(mContext, spyConfig,
+                Arrays.asList(badScanResult, goodScanResult), null);
+        assertThat(passpointAccessPoint.getConfig().SSID)
+                .isEqualTo(AccessPoint.convertToQuotedString(goodSsid));
+        passpointAccessPoint.setScanResultsPasspoint(
+                Arrays.asList(badScanResult, goodScanResult, bestScanResult), null);
+        assertThat(passpointAccessPoint.getConfig().SSID)
+                .isEqualTo(AccessPoint.convertToQuotedString(bestSsid));
+    }
+
+    /**
+     * Verifies that the OSU AccessPoint constructor creates AccessPoints whose isOsuProvider()
+     * returns true.
+     */
+    @Test
+    public void testOsuAccessPointConstructor_createdAccessPointIsOsuProvider() {
+        AccessPoint osuAccessPoint = new AccessPoint(mContext, createOsuProvider(),
+                mScanResults);
+
+        assertThat(osuAccessPoint.isOsuProvider()).isTrue();
+    }
+
+    /**
+     * Verifies that the summary of an OSU entry only shows the tap_to_sign_up string.
+     */
+    @Test
+    public void testOsuAccessPointSummary_showsTapToSignUp() {
+        AccessPoint osuAccessPoint = new AccessPoint(mContext, createOsuProvider(),
+                mScanResults);
+
+        assertThat(osuAccessPoint.getSummary())
+                .isEqualTo(mContext.getString(R.string.tap_to_sign_up));
+    }
+
+    @Test
+    public void testOsuAccessPointSummary_showsProvisioningUpdates() {
+        AccessPoint osuAccessPoint = new AccessPoint(mContext, createOsuProvider(),
+                mScanResults);
+
+        osuAccessPoint.setListener(mMockAccessPointListener);
+
+        AccessPoint.AccessPointProvisioningCallback provisioningCallback =
+                osuAccessPoint.new AccessPointProvisioningCallback();
+
+        int[] openingProviderStatuses = {
+                ProvisioningCallback.OSU_STATUS_AP_CONNECTING,
+                ProvisioningCallback.OSU_STATUS_AP_CONNECTED,
+                ProvisioningCallback.OSU_STATUS_SERVER_CONNECTING,
+                ProvisioningCallback.OSU_STATUS_SERVER_VALIDATED,
+                ProvisioningCallback.OSU_STATUS_SERVER_CONNECTED,
+                ProvisioningCallback.OSU_STATUS_INIT_SOAP_EXCHANGE,
+                ProvisioningCallback.OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE
+        };
+        int[] completingSignUpStatuses = {
+                ProvisioningCallback.OSU_STATUS_REDIRECT_RESPONSE_RECEIVED,
+                ProvisioningCallback.OSU_STATUS_SECOND_SOAP_EXCHANGE,
+                ProvisioningCallback.OSU_STATUS_THIRD_SOAP_EXCHANGE,
+                ProvisioningCallback.OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS,
+        };
+
+        for (int status : openingProviderStatuses) {
+            provisioningCallback.onProvisioningStatus(status);
+            assertThat(osuAccessPoint.getSummary())
+                    .isEqualTo(String.format(mContext.getString(R.string.osu_opening_provider),
+                            OSU_FRIENDLY_NAME));
+        }
+
+        provisioningCallback.onProvisioningFailure(0);
+        assertThat(osuAccessPoint.getSummary())
+                .isEqualTo(mContext.getString(R.string.osu_connect_failed));
+
+        for (int status : completingSignUpStatuses) {
+            provisioningCallback.onProvisioningStatus(status);
+            assertThat(osuAccessPoint.getSummary())
+                    .isEqualTo(mContext.getString(R.string.osu_completing_sign_up));
+        }
+
+        provisioningCallback.onProvisioningFailure(0);
+        assertThat(osuAccessPoint.getSummary())
+                .isEqualTo(mContext.getString(R.string.osu_sign_up_failed));
+
+        provisioningCallback.onProvisioningComplete();
+        assertThat(osuAccessPoint.getSummary())
+                .isEqualTo(mContext.getString(R.string.osu_sign_up_complete));
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 7d22788..edf414d 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -1155,8 +1155,7 @@
                 providersAndScans, cachedAccessPoints);
 
         // Verify second update AP is the same object as the first update AP
-        assertTrue(osuAccessPointsFirstUpdate.get(0)
-                == osuAccessPointsSecondUpdate.get(0));
+        assertThat(osuAccessPointsFirstUpdate.get(0)).isSameAs(osuAccessPointsSecondUpdate.get(0));
         // Verify second update AP has the average of the first and second update RSSIs
         assertThat(osuAccessPointsSecondUpdate.get(0).getRssi())
                 .isEqualTo((prevRssi + newRssi) / 2);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index 491f32d..bfda888 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -9,7 +9,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 
 import org.junit.Before;
@@ -17,17 +21,22 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowPackageManager;
 
 @RunWith(RobolectricTestRunner.class)
 public class TileTest {
 
+    private Context mContext;
     private ActivityInfo mActivityInfo;
     private Tile mTile;
 
     @Before
     public void setUp() {
+        mContext = RuntimeEnvironment.application;
         mActivityInfo = new ActivityInfo();
-        mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
+        mActivityInfo.applicationInfo = new ApplicationInfo();
+        mActivityInfo.packageName = mContext.getPackageName();
         mActivityInfo.name = "abc";
         mActivityInfo.icon = com.android.internal.R.drawable.ic_plus;
         mActivityInfo.metaData = new Bundle();
@@ -143,4 +152,21 @@
 
         assertThat(tile.getOrder()).isEqualTo(1);
     }
+
+    @Test
+    public void getTitle_shouldEnsureMetadataNotStale() {
+        final ResolveInfo info = new ResolveInfo();
+        info.activityInfo = mActivityInfo;
+        final ShadowPackageManager spm = Shadow.extract(mContext.getPackageManager());
+        spm.addResolveInfoForIntent(
+                new Intent().setClassName(mActivityInfo.packageName, mActivityInfo.name), info);
+
+        final Tile tile = new Tile(mActivityInfo, "category");
+        final long staleTimeStamp = -10000;
+        tile.mLastUpdateTime = staleTimeStamp;
+
+        tile.getTitle(RuntimeEnvironment.application);
+
+        assertThat(tile.mLastUpdateTime).isNotEqualTo(staleTimeStamp);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
index d5b89ca..c1c5fa9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -17,6 +17,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 
+import android.util.LongSparseLongArray;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -152,11 +153,12 @@
     }
 
     private OpEntry createOpEntryWithTime(int op, long time) {
-        final long[] times = new long[AppOpsManager._NUM_UID_STATE];
         // Slot for background access timestamp.
-        times[AppOpsManager.UID_STATE_LAST_NON_RESTRICTED + 1] = time;
-        final long[] rejectTimes = new long[AppOpsManager._NUM_UID_STATE];
-        return new OpEntry(op, AppOpsManager.MODE_ALLOWED, times, rejectTimes, 0 /* duration */,
-                0 /* proxyUid */, "" /* proxyPackage */);
+        final LongSparseLongArray accessTimes = new LongSparseLongArray();
+        accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_BACKGROUND,
+            AppOpsManager.OP_FLAG_SELF), time);
+
+        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes, null /*durations*/,
+            null /*rejectTimes*/, null /* proxyUids */, null /* proxyPackages */);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 08d5367..8bd5fd2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -17,6 +17,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 
+import android.util.LongSparseLongArray;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -153,6 +154,13 @@
     }
 
     private OpEntry createOpEntryWithTime(int op, long time, int duration) {
-        return new OpEntry(op, AppOpsManager.MODE_ALLOWED, time, 0L, duration, 0, "");
+        final LongSparseLongArray accessTimes = new LongSparseLongArray();
+        accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
+            AppOpsManager.OP_FLAG_SELF), time);
+        final LongSparseLongArray durations = new LongSparseLongArray();
+        durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
+            AppOpsManager.OP_FLAG_SELF), duration);
+        return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes,
+            null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java
index 29d57b7..2b27248 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartInfoTest.java
@@ -72,7 +72,8 @@
         final BarViewInfo barViewInfo = new BarViewInfo(
                 null /* icon */,
                 50,
-                mTitle);
+                mTitle,
+                null);
 
         final BarChartInfo mBarChartInfo = new BarChartInfo.Builder()
                 .setTitle(mTitle)
@@ -91,7 +92,8 @@
         final BarViewInfo barViewInfo = new BarViewInfo(
                 null /* icon */,
                 50,
-                mTitle);
+                mTitle,
+                null);
         final BarChartInfo mBarChartInfo = new BarChartInfo.Builder()
                 .setTitle(mTitle)
                 .setDetails(mDetails)
@@ -113,7 +115,8 @@
         final BarViewInfo barViewInfo = new BarViewInfo(
                 null /* icon */,
                 50,
-                mTitle);
+                mTitle,
+                null);
         new BarChartInfo.Builder()
                 .setTitle(mTitle)
                 .setDetails(mDetails)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
index 3acca2a..266554b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -113,7 +113,8 @@
         final BarChartInfo barChartInfo = new BarChartInfo.Builder()
                 .setTitle(R.string.debug_app)
                 .setDetails(R.string.debug_app)
-                .addBarViewInfo(new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app))
+                .addBarViewInfo(
+                        new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null))
                 .build();
 
         mPreference.initializeBarChart(barChartInfo);
@@ -128,7 +129,8 @@
         // We don't call BarChartInfo.Builder#setDetails yet.
         final BarChartInfo barChartInfo = new BarChartInfo.Builder()
                 .setTitle(R.string.debug_app)
-                .addBarViewInfo(new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app))
+                .addBarViewInfo(
+                        new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null))
                 .build();
 
         mPreference.initializeBarChart(barChartInfo);
@@ -144,7 +146,8 @@
                 .setDetails(R.string.debug_app)
                 .setDetailsOnClickListener(v -> {
                 })
-                .addBarViewInfo(new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app))
+                .addBarViewInfo(
+                        new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null))
                 .build();
 
         mPreference.initializeBarChart(barChartInfo);
@@ -157,7 +160,7 @@
     @Test
     public void setBarViewInfos_oneBarViewInfoSet_shouldShowOneBarView() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app)
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null)
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -175,8 +178,8 @@
     @Test
     public void setBarViewInfos_twoBarViewInfosSet_shouldShowTwoBarViews() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app)
+                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null)
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -195,9 +198,9 @@
     @Test
     public void setBarViewInfos_threeBarViewInfosSet_shouldShowThreeBarViews() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app)
+                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null)
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -217,10 +220,10 @@
     @Test
     public void setBarViewInfos_fourBarViewInfosSet_shouldShowFourBarViews() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 2 /* barNumber */, R.string.debug_app),
+                new BarViewInfo(mIcon, 20 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 2 /* barNumber */, R.string.debug_app, null),
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -242,11 +245,11 @@
         thrown.expect(IllegalStateException.class);
 
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 70 /* barNumber */, R.string.debug_app),
+                new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 70 /* barNumber */, R.string.debug_app, null),
         };
 
         mPreference.setBarViewInfos(barViewsInfo);
@@ -255,10 +258,10 @@
     @Test
     public void setBarViewInfos_barViewInfosSet_shouldBeSortedInDescending() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app),
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+                new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 50 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 5 /* barNumber */, R.string.debug_app, null),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null),
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -278,7 +281,7 @@
     @Test
     public void setBarViewInfos_validBarViewSummarySet_barViewShouldShowSummary() {
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{
-                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app),
+                new BarViewInfo(mIcon, 10 /* barNumber */, R.string.debug_app, null),
         };
 
         mPreference.initializeBarChart(mBarChartInfo);
@@ -291,7 +294,8 @@
 
     @Test
     public void setBarViewInfos_clickListenerForBarViewSet_barViewShouldHaveClickListener() {
-        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
+        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app,
+                null);
         viewInfo.setClickListener(v -> {
         });
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo};
@@ -306,7 +310,8 @@
 
     @Test
     public void onBindViewHolder_loadingStateIsTrue_shouldHideAllViews() {
-        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
+        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app,
+                null);
         viewInfo.setClickListener(v -> {
         });
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo};
@@ -322,7 +327,8 @@
 
     @Test
     public void onBindViewHolder_loadingStateIsFalse_shouldInitAnyView() {
-        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
+        final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app,
+                null);
         viewInfo.setClickListener(v -> {
         });
         final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo};
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 65e0c0f..d881858 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -215,6 +215,9 @@
     <!-- Default for Settings.System.VIBRATE_WHEN_RINGING -->
     <bool name="def_vibrate_when_ringing">false</bool>
 
+    <!-- Default for Settings.Global.APPLY_RAMPING_RINGER -->
+    <bool name="def_apply_ramping_ringer">false</bool>
+
     <!-- Default for Settings.Secure.CHARGING_VIBRATION_ENABLED -->
     <bool name="def_charging_vibration_enabled">true</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 0f8fd92..f7f34f6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1382,6 +1382,9 @@
                 Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
                 GlobalSettingsProto.TEXT_CLASSIFIER_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Global.TEXT_CLASSIFIER_ACTION_MODEL_PARAMS,
+                GlobalSettingsProto.TEXT_CLASSIFIER_ACTION_MODEL_PARAMS);
+        dumpSetting(s, p,
                 Settings.Global.THEATER_MODE_ON,
                 GlobalSettingsProto.THEATER_MODE_ON);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index d6c33a3..2c2987c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3237,7 +3237,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 174;
+            private static final int SETTINGS_VERSION = 175;
 
             private final int mUserId;
 
@@ -4270,6 +4270,24 @@
                     currentVersion = 174;
                 }
 
+                if (currentVersion == 174) {
+                    // Version 174: Set the default value for Global Settings: APPLY_RAMPING_RINGER
+
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+
+                    Setting currentRampingRingerSetting = globalSettings.getSettingLocked(
+                            Settings.Global.APPLY_RAMPING_RINGER);
+                    if (currentRampingRingerSetting.isNull()) {
+                        globalSettings.insertSettingLocked(
+                                Settings.Global.APPLY_RAMPING_RINGER,
+                                getContext().getResources().getBoolean(
+                                        R.bool.def_apply_ramping_ringer) ? "1" : "0", null,
+                                true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 175;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 265d464..9d6fc9ed 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -42,6 +42,7 @@
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.DUMP" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
     <uses-permission android:name="android.permission.STATUS_BAR" />
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
new file mode 100644
index 0000000..7c72688
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActionsPanelPlugin.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins;
+
+import android.view.View;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Plugin which provides a "Panel" {@link View} to be rendered inside of the GlobalActions menu.
+ *
+ * Implementations should construct a new {@link PanelViewController} with the given
+ * {@link Callbacks} instance inside of {@link #onPanelShown(Callbacks)}, and should not hold onto
+ * a reference, instead allowing Global Actions to manage the lifetime of the object.
+ *
+ * Under this assumption, {@link PanelViewController} represents the lifetime of a single invocation
+ * of the Global Actions menu. The {@link View} for the Panel is generated when the
+ * {@link PanelViewController} is constructed, and {@link PanelViewController#getPanelContent()}
+ * serves as a simple getter. When Global Actions is dismissed,
+ * {@link PanelViewController#onDismissed()} can be used to cleanup any resources allocated when
+ * constructed. Global Actions will then release the reference, and the {@link PanelViewController}
+ * will be garbage-collected.
+ */
+@ProvidesInterface(
+        action = GlobalActionsPanelPlugin.ACTION, version = GlobalActionsPanelPlugin.VERSION)
+@DependsOn(target = GlobalActionsPanelPlugin.Callbacks.class)
+@DependsOn(target = GlobalActionsPanelPlugin.PanelViewController.class)
+public interface GlobalActionsPanelPlugin extends Plugin {
+    String ACTION = "com.android.systemui.action.PLUGIN_GLOBAL_ACTIONS_PANEL";
+    int VERSION = 0;
+
+    /**
+     * Invoked when the GlobalActions menu is shown.
+     *
+     * @param callbacks {@link Callbacks} instance that can be used by the Panel to interact with
+     *                  the Global Actions menu.
+     * @return A {@link PanelViewController} instance used to receive Global Actions events.
+     */
+    PanelViewController onPanelShown(Callbacks callbacks);
+
+    /**
+     * Provides methods to interact with the Global Actions menu.
+     */
+    @ProvidesInterface(version = Callbacks.VERSION)
+    interface Callbacks {
+        int VERSION = 0;
+
+        /** Dismisses the Global Actions menu. */
+        void dismissGlobalActionsMenu();
+    }
+
+    /**
+     * Receives Global Actions events, and provides the Panel {@link View}.
+     */
+    @ProvidesInterface(version = PanelViewController.VERSION)
+    interface PanelViewController {
+        int VERSION = 0;
+
+        /**
+         * Returns the {@link View} for the Panel to be rendered in Global Actions. This View can be
+         * any size, and will be rendered above the Global Actions menu when z-ordered.
+         */
+        View getPanelContent();
+
+        /**
+         * Invoked when the Global Actions menu (containing the View returned from
+         * {@link #getPanelContent()}) is dismissed.
+         */
+        void onDismissed();
+    }
+}
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png
deleted file mode 100644
index 035a4df..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_preview.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_clock.xml
index f4a7376..89bbc09 100644
--- a/packages/SystemUI/res-keyguard/layout/type_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/type_clock.xml
@@ -21,10 +21,10 @@
   >
   <com.android.keyguard.clock.TypographicClock
       android:id="@+id/type_clock"
-      android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
-      android:paddingLeft="50dp"
+      android:paddingStart="50dp"
+      android:textAlignment="viewStart"
       style="@style/widget_big"
       android:textSize="40dp"
       />
diff --git a/packages/SystemUI/res/drawable/btn_restart.xml b/packages/SystemUI/res/drawable/btn_restart.xml
new file mode 100644
index 0000000..73a48d3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/btn_restart.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#aa000000"
+        android:pathData="M0,12 a12,12 0 1,0 24,0 a12,12 0 1,0 -24,0" />
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M17.65,6.35c-1.63,-1.63 -3.94,-2.57 -6.48,-2.31c-3.67,0.37 -6.69,3.35 -7.1,7.02C3.52,15.91 7.27,20 12,20c3.19,0 5.93,-1.87 7.21,-4.57c0.31,-0.66 -0.16,-1.43 -0.89,-1.43h-0.01c-0.37,0 -0.72,0.2 -0.88,0.53c-1.13,2.43 -3.84,3.97 -6.81,3.32c-2.22,-0.49 -4.01,-2.3 -4.49,-4.52C5.31,9.44 8.26,6 12,6c1.66,0 3.14,0.69 4.22,1.78l-2.37,2.37C13.54,10.46 13.76,11 14.21,11H19c0.55,0 1,-0.45 1,-1V5.21c0,-0.45 -0.54,-0.67 -0.85,-0.35L17.65,6.35z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/global_action_panel_scrim.xml b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
new file mode 100644
index 0000000..177b8d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/global_action_panel_scrim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <gradient
+        android:centerY="0.45"
+        android:startColor="#be3c4043"
+        android:centerColor="#be3c4043"
+        android:endColor="#4d3c4043"
+        android:angle="270" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml
index 84c793f..672abf1 100644
--- a/packages/SystemUI/res/drawable/qs_detail_background.xml
+++ b/packages/SystemUI/res/drawable/qs_detail_background.xml
@@ -14,6 +14,20 @@
     limitations under the License.
 -->
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@color/qs_detail_transition" />
-    <item android:drawable="?android:attr/colorPrimary" />
+    <item>
+        <inset>
+            <shape>
+                <solid android:color="@color/qs_detail_transition"/>
+                <corners android:radius="?android:attr/dialogCornerRadius" />
+            </shape>
+        </inset>
+    </item>
+    <item>
+        <inset>
+            <shape>
+                <solid android:color="?android:attr/colorPrimary"/>
+                <corners android:radius="?android:attr/dialogCornerRadius" />
+            </shape>
+        </inset>
+    </item>
 </transition>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
index 480f523..235d0fc 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -10,14 +10,12 @@
     android:gravity="top|right"
     android:clipChildren="false"
 >
-
     <LinearLayout
         android:layout_height="match_parent"
         android:layout_width="wrap_content"
         android:gravity="top|right"
         android:padding="0dp"
         android:orientation="vertical"
-        android:layoutDirection="ltr"
         android:layout_marginRight="@dimen/global_actions_grid_container_bottom_margin"
     >
         <!-- Grid of action items -->
@@ -26,7 +24,6 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:layoutDirection="ltr"
             android:layout_marginTop="@dimen/global_actions_grid_side_margin"
             android:translationZ="@dimen/global_actions_translate"
             android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
@@ -39,25 +36,21 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="ltr"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="ltr"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="ltr"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
         </com.android.systemui.globalactions.ListGridLayout>
-
         <!-- For separated items-->
         <LinearLayout
             android:id="@+id/separated_button"
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
index 4f86826..e028214 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -10,7 +10,6 @@
     android:gravity="top|left"
     android:clipChildren="false"
 >
-
     <LinearLayout
         android:layout_height="match_parent"
         android:layout_width="wrap_content"
@@ -37,11 +36,11 @@
             android:gravity="center"
             android:translationZ="@dimen/global_actions_translate"
         />
-
         <!-- Grid of action items -->
         <com.android.systemui.globalactions.ListGridLayout
             android:id="@android:id/list"
             android:layout_gravity="bottom|left"
+            android:gravity="right"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="vertical"
@@ -54,28 +53,22 @@
             android:background="?android:attr/colorBackgroundFloating"
         >
             <LinearLayout
-                android:layout_gravity="bottom"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="rtl"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
             <LinearLayout
-                android:layout_gravity="bottom"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="rtl"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
             <LinearLayout
-                android:layout_gravity="bottom"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:layoutDirection="rtl"
-                android:orientation="horizontal"
+                android:layoutDirection="locale"
             />
         </com.android.systemui.globalactions.ListGridLayout>
     </LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index 729e96e..a620a8e 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -10,7 +10,6 @@
     android:gravity="bottom|center"
     android:clipChildren="false"
 >
-
     <LinearLayout
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
@@ -35,14 +34,13 @@
             android:gravity="center"
             android:translationZ="@dimen/global_actions_translate"
         />
-
         <!-- Grid of action items -->
         <com.android.systemui.globalactions.ListGridLayout
             android:id="@android:id/list"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layoutDirection="rtl"
+            android:orientation="vertical"
+            android:gravity="right"
             android:layout_marginRight="@dimen/global_actions_grid_side_margin"
             android:translationZ="@dimen/global_actions_translate"
             android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
@@ -55,19 +53,19 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:orientation="vertical"
+                android:layoutDirection="locale"
             />
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:orientation="vertical"
+                android:layoutDirection="locale"
             />
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:visibility="gone"
-                android:orientation="vertical"
+                android:layoutDirection="locale"
             />
         </com.android.systemui.globalactions.ListGridLayout>
     </LinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 863c1cc..7e0f3ae 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -44,7 +44,7 @@
             android:id="@+id/pkgname"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
             android:layout_marginStart="3dp"
             android:layout_marginEnd="2dp"
             android:singleLine="true"
@@ -54,7 +54,7 @@
             android:id="@+id/pkg_divider"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
             android:text="@*android:string/notification_header_divider_symbol"
@@ -64,7 +64,7 @@
             android:id="@+id/delegate_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
             android:ellipsize="end"
@@ -129,7 +129,7 @@
                     android:id="@+id/group_name"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
                     android:layout_marginStart="2dp"
                     android:layout_marginEnd="2dp"
                     android:ellipsize="end"
@@ -139,7 +139,7 @@
                     android:id="@+id/pkg_group_divider"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
+                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
                     android:layout_marginStart="2dp"
                     android:layout_marginEnd="2dp"
                     android:text="@*android:string/notification_header_divider_symbol"
@@ -151,7 +151,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
-                    style="@android:style/TextAppearance.Material.Notification.Title"
+                    style="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
                     android:layout_toEndOf="@id/pkg_group_divider"/>
             </RelativeLayout>
             <!-- Question prompt -->
@@ -159,7 +159,7 @@
                 android:id="@+id/block_prompt"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                style="@android:style/TextAppearance.Material.Notification" />
+                style="@*android:style/TextAppearance.DeviceDefault.Notification" />
         </LinearLayout>
 
         <!-- Settings and Done buttons -->
@@ -174,7 +174,7 @@
             android:clipToPadding="false">
             <TextView
                 android:id="@+id/done"
-                android:text="@string/inline_done_button"
+                android:text="@string/inline_ok_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
@@ -191,7 +191,7 @@
                 android:orientation="horizontal">
                 <TextView
                     android:id="@+id/deliver_silently"
-                    android:text="@string/inline_deliver_silently_button"
+                    android:text="@string/inline_silent_button_silent"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_centerVertical="true"
diff --git a/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml b/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml
index 5bcc1b3..b969a15 100644
--- a/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_footer_dialog.xml
@@ -39,17 +39,14 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/monitoring_title_device_owned"
-                style="@style/TextAppearance.DeviceManagementDialog.Title"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/DeviceManagementDialogTitle"
                 android:paddingBottom="@dimen/qs_footer_dialog_subtitle_padding"
             />
             <TextView
                 android:id="@+id/device_management_warning"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@null"
-                style="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textAppearance="@style/TextAppearance.DeviceManagementDialog.Content"
             />
         </LinearLayout>
 
@@ -64,17 +61,14 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/monitoring_subtitle_ca_certificate"
-                style="@style/TextAppearance.DeviceManagementDialog.Title"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/DeviceManagementDialogTitle"
                 android:paddingBottom="@dimen/qs_footer_dialog_subtitle_padding"
             />
             <TextView
                 android:id="@+id/ca_certs_warning"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@null"
-                style="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textAppearance="@style/TextAppearance.DeviceManagementDialog.Content"
             />
         </LinearLayout>
 
@@ -89,17 +83,14 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/monitoring_subtitle_network_logging"
-                style="@style/TextAppearance.DeviceManagementDialog.Title"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/DeviceManagementDialogTitle"
                 android:paddingBottom="@dimen/qs_footer_dialog_subtitle_padding"
             />
             <TextView
                 android:id="@+id/network_logging_warning"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@null"
-                style="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textAppearance="@style/TextAppearance.DeviceManagementDialog.Content"
             />
         </LinearLayout>
 
@@ -114,17 +105,14 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/monitoring_subtitle_vpn"
-                style="@style/TextAppearance.DeviceManagementDialog.Title"
-                android:textColor="?android:attr/textColorPrimary"
+                style="@style/DeviceManagementDialogTitle"
                 android:paddingBottom="@dimen/qs_footer_dialog_subtitle_padding"
             />
             <TextView
                 android:id="@+id/vpn_warning"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@null"
-                style="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textAppearance="@style/TextAppearance.DeviceManagementDialog.Content"
             />
         </LinearLayout>
     </LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
index cdad94b..8dcddc2 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
@@ -31,7 +31,7 @@
         android:paddingStart="48dp"
         android:paddingTop="43dp"
         android:text="@string/screen_pinning_title"
-        android:textColor="@color/screen_pinning_primary_text"
+        android:textColor="@android:color/white"
         android:textSize="24sp" />
 
     <TextView
@@ -43,7 +43,7 @@
         android:paddingStart="48dp"
         android:paddingTop="12.6dp"
         android:text="@string/screen_pinning_description"
-        android:textColor="@color/screen_pinning_primary_text"
+        android:textColor="@android:color/white"
         android:textSize="16sp" />
 
     <Button
diff --git a/packages/SystemUI/res/layout/size_compat_mode_hint.xml b/packages/SystemUI/res/layout/size_compat_mode_hint.xml
new file mode 100644
index 0000000..347c2b4
--- /dev/null
+++ b/packages/SystemUI/res/layout/size_compat_mode_hint.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@android:color/background_light"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="180dp"
+        android:layout_height="wrap_content"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp"
+        android:paddingTop="10dp"
+        android:text="@string/restart_button_description"
+        android:textAlignment="viewStart"
+        android:textColor="@android:color/primary_text_light"
+        android:textSize="16sp" />
+
+    <Button
+        android:id="@+id/got_it"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:includeFontPadding="false"
+        android:layout_gravity="end"
+        android:minHeight="36dp"
+        android:background="?android:attr/selectableItemBackground"
+        android:text="@string/got_it"
+        android:textAllCaps="true"
+        android:textColor="#3c78d8"
+        android:textSize="16sp"
+        android:textStyle="bold" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
index 586cdf3..716e127 100644
--- a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
+++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
@@ -1,27 +1,76 @@
 precision mediump float;
 
+// The actual wallpaper texture.
 uniform sampler2D uTexture;
-uniform float uCenterReveal;
+
+// The 85th percenile for the luminance histogram of the image (a value between 0 and 1).
+// This value represents the point in histogram that includes 85% of the pixels of the image.
+uniform float uPer85;
+
+// Reveal is the animation value that goes from 1 (the image is hidden) to 0 (the image is visible).
 uniform float uReveal;
+
+// The opacity of locked screen (constant value).
 uniform float uAod2Opacity;
 varying vec2 vTextureCoordinates;
 
+/*
+ * Calculates the relative luminance of the pixel.
+ */
 vec3 luminosity(vec3 color) {
     float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
     return vec3(lum);
 }
 
 vec4 transform(vec3 diffuse) {
-    // TODO: Add well comments here, tracking on b/123615467.
+    // Getting the luminance for this pixel
     vec3 lum = luminosity(diffuse);
-    diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal));
-    float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal));
-    diffuse = smoothstep(val, 1.0, diffuse);
-    diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal));
+
+    /*
+     * while the reveal > per85, it shows the luminance image (B&W image)
+     * then when moving passed that value, the image gets colored.
+     */
+    float trans = smoothstep(0., uPer85, uReveal);
+    diffuse = mix(diffuse, lum, trans);
+
+    // 'lower' value represents the capped 'reveal' value to the range [0, per85]
+    float selector = step(uPer85, uReveal);
+    float lower = mix(uReveal, uPer85, selector);
+
+    /*
+     * Remaps image:
+     * - from reveal=1 to reveal=per85 => lower=per85, diffuse=luminance
+     *   That means that remaps black and white image pixel
+     *   from a possible values of [0,1] to [per85, 1] (if the pixel is darker than per85,
+     *   it's gonna be black, if it's between per85 and 1, it's gonna be gray
+     *   and if it's 1 it's gonna be white).
+     * - from reveal=per85 to reveal=0 => lower=reveal, 'diffuse' changes from luminance to color
+     *   That means that remaps each image pixel color (rgb)
+     *   from a possible values of [0,1] to [lower, 1] (if the pixel color is darker than 'lower',
+     *   it's gonna be 0, if it's between 'lower' and 1, it's gonna be remap to a value
+     *   between 0 and 1 and if it's 1 it's gonna be 1).
+     * - if reveal=0 => lower=0, diffuse=color image
+     *   The image is shown as it is, colored.
+     */
+    vec3 remaps = smoothstep(lower, 1., diffuse);
+
+    // Interpolate between diffuse and remaps using reveal to avoid over saturation.
+    diffuse = mix(diffuse, remaps, uReveal);
+
+    /*
+     * Fades in the pixel value:
+     * - if reveal=1 => fadeInOpacity=0
+     * - from reveal=1 to reveal=per85 => 0<=fadeInOpacity<=1
+     * - if reveal>per85 => fadeInOpacity=1
+     */
+    float fadeInOpacity = 1. - smoothstep(uPer85, 1., uReveal);
+    diffuse *= uAod2Opacity * fadeInOpacity;
+
     return vec4(diffuse.r, diffuse.g, diffuse.b, 1.);
 }
 
 void main() {
+    // gets the pixel value of the wallpaper for this uv coordinates on screen.
     vec4 fragColor = texture2D(uTexture, vTextureCoordinates);
     gl_FragColor = transform(fragColor.rgb);
 }
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index b4dc0eff..1d56680 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -311,6 +311,7 @@
         <item>com.android.systemui.ScreenDecorations</item>
         <item>com.android.systemui.biometrics.BiometricDialogImpl</item>
         <item>com.android.systemui.SliceBroadcastRelayHandler</item>
+        <item>com.android.systemui.SizeCompatModeActivityController</item>
     </string-array>
 
     <!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 50cf37b..a40a14a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -856,6 +856,9 @@
     <!-- Global actions grid layout -->
     <dimen name="global_actions_grid_side_margin">4dp</dimen>
 
+    <!-- Global actions panel -->
+    <dimen name="global_actions_panel_top_margin">85dp</dimen>
+
     <!-- The maximum offset in either direction that elements are moved horizontally to prevent
          burn-in on AOD. -->
     <dimen name="burn_in_prevention_offset_x">8dp</dimen>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 38f469e..67293c5 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -18,8 +18,8 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Date format for display: should match the lockscreen in /policy.  -->
-    <string name="system_ui_date_pattern">@*android:string/system_ui_date_pattern</string>
+    <string name="system_ui_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</string>
 
     <!-- Date format for the always on display.  -->
-    <item type="string" name="system_ui_aod_date_pattern">eeeMMMd</item>
+    <item type="string" name="system_ui_aod_date_pattern" translatable="false">eeeMMMd</item>
 </resources>
diff --git a/packages/SystemUI/res/values/internal.xml b/packages/SystemUI/res/values/internal.xml
index e0d3cd2..930cfce 100644
--- a/packages/SystemUI/res/values/internal.xml
+++ b/packages/SystemUI/res/values/internal.xml
@@ -18,6 +18,5 @@
     <dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
     <dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
     <dimen name="navigation_bar_height_car_mode">@*android:dimen/navigation_bar_height_car_mode</dimen>
-    <color name="screen_pinning_primary_text">@*android:color/primary_text_default_material_light</color>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5338bb4..9e9aada 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -651,8 +651,6 @@
 
     <!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "+ 3" [CHAR LIMIT=5] -->
     <string name="notification_group_overflow_indicator">+ <xliff:g id="number" example="3">%s</xliff:g></string>
-    <!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "New message, +3" [CHAR LIMIT=7] -->
-    <string name="notification_group_overflow_indicator_ambient"><xliff:g id="notification_title" example="New message">%1$s</xliff:g>, +<xliff:g id="overflow" example="+3">%2$s</xliff:g></string>
 
     <!-- Content description describing how many more notifications are in a group [CHAR LIMIT=NONE] -->
     <plurals name="notification_group_overflow_description">
@@ -1582,6 +1580,9 @@
     <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
     <string name="inline_done_button">Done</string>
 
+    <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
+    <string name="inline_ok_button">OK</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
     <string name="inline_keep_showing">Keep showing these notifications?</string>
 
@@ -2373,6 +2374,9 @@
     <!-- What to show on the ambient display player when song doesn't have a title. [CHAR LIMIT=20] -->
     <string name="music_controls_no_title">No title</string>
 
+    <!-- Description of the restart button in the hint of size compatibility mode. [CHAR LIMIT=NONE] -->
+    <string name="restart_button_description">Tap to restart this app and go full screen.</string>
+
     <!-- Text used for content description of deep link button in the header of expanded bubble
          view. [CHAR_LIMIT=NONE] -->
     <string name="bubbles_deep_link_button_description">Open <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 30dbc8b..fc7a56f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -71,11 +71,11 @@
 
     <style name="hybrid_notification_title">
         <item name="android:paddingEnd">4dp</item>
-        <item name="android:textAppearance">@*android:style/TextAppearance.Material.Notification.Title</item>
+        <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault.Notification.Title</item>
     </style>
 
     <style name="hybrid_notification_text"
-           parent="@*android:style/Widget.Material.Notification.Text">
+           parent="@*android:style/Widget.DeviceDefault.Notification.Text">
         <item name="android:paddingEnd">4dp</item>
     </style>
 
@@ -239,10 +239,19 @@
         <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
     </style>
 
-    <style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
-        <item name="android:gravity">center</item>
+    <style name="TextAppearance.DeviceManagementDialog">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
+    <style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
+
+    <style name="DeviceManagementDialogTitle">
+        <item name="android:gravity">center</item>
+        <item name="android:textAppearance">@style/TextAppearance.DeviceManagementDialog.Title</item>
+    </style>
+
+    <style name="TextAppearance.DeviceManagementDialog.Content" parent="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
+
     <style name="BaseBrightnessDialogContainer" parent="@style/Theme.SystemUI">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
@@ -327,10 +336,6 @@
         <item name="android:gravity">center</item>
     </style>
 
-    <style name="TextAppearance.Material.Notification.HeaderTitle"
-        parent="@*android:style/TextAppearance.Material.Notification.Info">
-    </style>
-
     <style name="SearchPanelCircle">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
@@ -460,7 +465,7 @@
     </style>
 
     <style name="TextAppearance.HeadsUpStatusBarText"
-           parent="@*android:style/TextAppearance.Material.Notification.Info">
+           parent="@*android:style/TextAppearance.DeviceDefault.Notification.Info">
     </style>
 
     <style name="TextAppearance.QSEdit.Headers"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 46ed715b..0f71ffb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shared.system;
 
+import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
 import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
@@ -464,6 +465,17 @@
     }
 
     /**
+     * @return whether lock task mode is active in kiosk-mode (not screen pinning).
+     */
+    public boolean isLockTaskKioskModeActive() {
+        try {
+            return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_LOCKED;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Shows a voice session identified by {@code token}
      * @return true if the session was shown, false otherwise
      */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/DevicePolicyManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DevicePolicyManagerWrapper.java
new file mode 100644
index 0000000..c6722ae
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/DevicePolicyManagerWrapper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.app.AppGlobals;
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * Wrapper for {@link DevicePolicyManager}.
+ */
+public class DevicePolicyManagerWrapper {
+    private static final DevicePolicyManagerWrapper sInstance = new DevicePolicyManagerWrapper();
+
+    private static final DevicePolicyManager sDevicePolicyManager =
+            AppGlobals.getInitialApplication().getSystemService(DevicePolicyManager.class);
+
+    private DevicePolicyManagerWrapper() { }
+
+    public static DevicePolicyManagerWrapper getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * Returns whether the given package is allowed to run in Lock Task mode.
+     */
+    public boolean isLockTaskPermitted(String pkg) {
+        return sDevicePolicyManager.isLockTaskPermitted(pkg);
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
index 32e4bbf..443c1e1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PackageManagerWrapper.java
@@ -22,8 +22,10 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.ResolveInfoFlags;
 import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
+import android.os.UserHandle;
 
 import java.util.List;
 
@@ -40,6 +42,8 @@
         return sInstance;
     }
 
+    private PackageManagerWrapper() {}
+
     /**
      * @return the activity info for a given {@param componentName} and {@param userId}.
      */
@@ -65,4 +69,19 @@
             return null;
         }
     }
+
+    /**
+     * Determine the best Activity to perform for a given Intent.
+     */
+    public ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags) {
+        final String resolvedType =
+                intent.resolveTypeIfNeeded(AppGlobals.getInitialApplication().getContentResolver());
+        try {
+            return mIPackageManager.resolveIntent(
+                    intent, resolvedType, flags, UserHandle.getCallingUserId());
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index c54a469..f2a961d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.ComponentName;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.util.Log;
 
@@ -73,6 +74,7 @@
     }
 
     public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
+    public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { }
 
     /**
      * Checks that the current user matches the process. Since
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 7e4ab85..6e3eb7c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -23,6 +23,7 @@
 import android.app.TaskStackListener;
 import android.content.ComponentName;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
@@ -180,6 +181,12 @@
                 requestedOrientation).sendToTarget();
     }
 
+    @Override
+    public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
+        mHandler.obtainMessage(H.ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED, displayId, 0 /* unused */,
+                activityToken).sendToTarget();
+    }
+
     private final class H extends Handler {
         private static final int ON_TASK_STACK_CHANGED = 1;
         private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -197,6 +204,7 @@
         private static final int ON_TASK_MOVED_TO_FRONT = 14;
         private static final int ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE = 15;
         private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED = 16;
+        private static final int ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED = 17;
 
 
         public H(Looper looper) {
@@ -319,6 +327,13 @@
                         }
                         break;
                     }
+                    case ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onSizeCompatModeActivityChanged(
+                                    msg.arg1, (IBinder) msg.obj);
+                        }
+                        break;
+                    }
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 563b007..d40fa66 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,6 +1,7 @@
 package com.android.keyguard;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.WallpaperManager;
@@ -31,6 +32,9 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
 import java.util.TimeZone;
 
 /**
@@ -148,6 +152,7 @@
         Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
         Dependency.get(SysuiColorExtractor.class)
             .removeOnColorsChangedListener(mColorsListener);
+        setClockPlugin(null);
     }
 
     private void setClockPlugin(ClockPlugin plugin) {
@@ -332,6 +337,19 @@
         return mStateListener;
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("KeyguardClockSwitch:");
+        pw.println("  mClockPlugin: " + mClockPlugin);
+        pw.println("  mClockView: " + mClockView);
+        pw.println("  mSmallClockFrame: " + mSmallClockFrame);
+        pw.println("  mBigClockContainer: " + mBigClockContainer);
+        pw.println("  mKeyguardStatusArea: " + mKeyguardStatusArea);
+        pw.println("  mDarkAmount: " + mDarkAmount);
+        pw.println("  mShowingHeader: " + mShowingHeader);
+        pw.println("  mSupportsDarkText: " + mSupportsDarkText);
+        pw.println("  mColorPalette: " + Arrays.toString(mColorPalette));
+    }
+
     /**
      * Special layout transition that scales the clock view as its bounds change, to make it look
      * like the text is shrinking.
@@ -371,11 +389,23 @@
                 boundsAnimator.addUpdateListener(animation -> {
                     float scale = MathUtils.lerp(startScale, 1f /* stop */,
                             animation.getAnimatedFraction());
-                    mClockView.setPivotX(mClockView.getWidth() / 2);
+                    mClockView.setPivotX(mClockView.getWidth() / 2f);
                     mClockView.setPivotY(0);
                     mClockView.setScaleX(scale);
                     mClockView.setScaleY(scale);
                 });
+                boundsAnimator.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animator) {
+                        mClockView.setScaleX(1f);
+                        mClockView.setScaleY(1f);
+                    }
+
+                    @Override
+                    public void onAnimationCancel(Animator animator) {
+                        onAnimationEnd(animator);
+                    }
+                });
             }
 
             return animator;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 2040a76..8ebe1ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -64,6 +64,8 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -174,6 +176,7 @@
             if (mContentChangeListener != null) {
                 mContentChangeListener.run();
             }
+            Trace.endSection();
             return;
         }
 
@@ -375,6 +378,17 @@
         Trace.endSection();
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("KeyguardSliceView:");
+        pw.println("  mClickActions: " + mClickActions);
+        pw.println("  mTitle: " + (mTitle == null ? "null" : mTitle.getVisibility() == VISIBLE));
+        pw.println("  mRow: " + (mRow == null ? "null" : mRow.getVisibility() == VISIBLE));
+        pw.println("  mTextColor: " + Integer.toHexString(mTextColor));
+        pw.println("  mDarkAmount: " + mDarkAmount);
+        pw.println("  mSlice: " + mSlice);
+        pw.println("  mHasHeader: " + mHasHeader);
+    }
+
     public static class Row extends LinearLayout {
 
         /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 17546c5..808e264 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -41,6 +41,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.Locale;
 import java.util.TimeZone;
 
@@ -289,6 +291,24 @@
         return false;
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("KeyguardStatusView:");
+        pw.println("  mOwnerInfo: " + (mOwnerInfo == null
+                ? "null" : mOwnerInfo.getVisibility() == VISIBLE));
+        pw.println("  mPulsing: " + mPulsing);
+        pw.println("  mDarkAmount: " + mDarkAmount);
+        pw.println("  mTextColor: " + Integer.toHexString(mTextColor));
+        if (mLogoutView != null) {
+            pw.println("  logout visible: " + (mLogoutView.getVisibility() == VISIBLE));
+        }
+        if (mClockView != null) {
+            mClockView.dump(fd, pw, args);
+        }
+        if (mKeyguardSlice != null) {
+            mKeyguardSlice.dump(fd, pw, args);
+        }
+    }
+
     // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
     // This is an optimization to ensure we only recompute the patterns when the inputs change.
     private static final class Patterns {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f208118..32e447b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1602,7 +1602,7 @@
                 (mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
                 shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
                 && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
-                && !mKeyguardGoingAway && mIsPrimaryUser;
+                && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser;
         return shouldListen;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 592b603..39a5842 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -355,15 +355,23 @@
         if (mBatteryPercentView != null) {
             if (mShowPercentMode == MODE_ESTIMATE && !mCharging) {
                 mBatteryController.getEstimatedTimeRemainingString((String estimate) -> {
-                    mBatteryPercentView.setText(estimate);
+                    if (estimate != null) {
+                        mBatteryPercentView.setText(estimate);
+                    } else {
+                        setPercentTextAtCurrentLevel();
+                    }
                 });
             } else {
-                mBatteryPercentView.setText(
-                        NumberFormat.getPercentInstance().format(mLevel / 100f));
+                setPercentTextAtCurrentLevel();
             }
         }
     }
 
+    private void setPercentTextAtCurrentLevel() {
+        mBatteryPercentView.setText(
+                NumberFormat.getPercentInstance().format(mLevel / 100f));
+    }
+
     private void updateShowPercent() {
         final boolean showing = mBatteryPercentView != null;
         final boolean systemSetting = 0 != Settings.System
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 87f004f..b7d1900 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -48,6 +48,9 @@
 import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
@@ -188,7 +191,7 @@
             new DependencyKey<>(LEAK_REPORT_EMAIL_NAME);
 
     private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>();
-    private final ArrayMap<Object, DependencyProvider> mProviders = new ArrayMap<>();
+    private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>();
 
     @Inject Lazy<ActivityStarter> mActivityStarter;
     @Inject Lazy<ActivityStarterDelegate> mActivityStarterDelegate;
@@ -285,6 +288,9 @@
     @Nullable
     @Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
     @Inject Lazy<ClockManager> mClockManager;
+    @Inject Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
+    @Inject Lazy<DevicePolicyManagerWrapper> mDevicePolicyManagerWrapper;
+    @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper;
 
     @Inject
     public Dependency() {
@@ -452,6 +458,9 @@
                 mForegroundServiceNotificationListener::get);
         mProviders.put(ClockManager.class, mClockManager::get);
         mProviders.put(PrivacyItemController.class, mPrivacyItemController::get);
+        mProviders.put(ActivityManagerWrapper.class, mActivityManagerWrapper::get);
+        mProviders.put(DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper::get);
+        mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get);
 
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
@@ -501,7 +510,7 @@
         Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>);
 
         @SuppressWarnings("unchecked")
-        DependencyProvider<T> provider = mProviders.get(cls);
+        LazyDependencyCreator<T> provider = mProviders.get(cls);
         if (provider == null) {
             throw new IllegalArgumentException("Unsupported dependency " + cls
                     + ". " + mProviders.size() + " providers known.");
@@ -511,7 +520,11 @@
 
     private static Dependency sDependency;
 
-    public interface DependencyProvider<T> {
+    /**
+     * Interface for a class that can create a dependency. Used to implement laziness
+     * @param <T> The type of the dependency being created
+     */
+    private interface LazyDependencyCreator<T> {
         T createDependency();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index a517d7c..895f9b9 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -41,6 +41,9 @@
 import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
@@ -181,4 +184,22 @@
             @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
         return new AutoHideController(context, mainHandler);
     }
+
+    @Singleton
+    @Provides
+    public ActivityManagerWrapper provideActivityManagerWrapper() {
+        return ActivityManagerWrapper.getInstance();
+    }
+
+    @Singleton
+    @Provides
+    public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() {
+        return DevicePolicyManagerWrapper.getInstance();
+    }
+
+    @Singleton
+    @Provides
+    public PackageManagerWrapper providePackageManagerWrapper() {
+        return PackageManagerWrapper.getInstance();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index f5451e9..26c5ef9 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -90,7 +90,7 @@
     }
 
     @Override
-    public ViewGroup getParentView(boolean separated, int index, boolean reverse) {
+    public ViewGroup getParentView(boolean separated, int index, int rotation) {
         if (separated) {
             return getSeparatedView();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index 8c49d56..8259da6 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -57,12 +57,12 @@
      * @param separated Whether or not this index refers to a position in the separated or list
      *                  container.
      * @param index The index of the item within the container.
-     * @param reverse If the MultiListLayout contains sub-lists within the list container, reverse
-     *                the order that they are filled.
+     * @param rotation Specifies the rotation of the device, which is used in some cases to
+     *                 determine child ordering.
      * @return The parent ViewGroup which will be used to contain the specified item
      * after it has been added to the layout.
      */
-    public abstract ViewGroup getParentView(boolean separated, int index, boolean reverse);
+    public abstract ViewGroup getParentView(boolean separated, int index, int rotation);
 
     /**
      * Sets the divided view, which may have a differently-colored background.
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index ab077d6..c0f03a6 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -471,6 +471,7 @@
             lp.width = WRAP_CONTENT;
             lp.height = MATCH_PARENT;
         }
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
         return lp;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
new file mode 100644
index 0000000..7a54344
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.hardware.display.DisplayManager;
+import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.CommandQueue;
+
+import java.lang.ref.WeakReference;
+
+/** Shows a restart-activity button when the foreground activity is in size compatibility mode. */
+public class SizeCompatModeActivityController extends SystemUI implements CommandQueue.Callbacks {
+    private static final String TAG = "SizeCompatMode";
+
+    /** The showing buttons by display id. */
+    private final SparseArray<RestartActivityButton> mActiveButtons = new SparseArray<>(1);
+    /** Avoid creating display context frequently for non-default display. */
+    private final SparseArray<WeakReference<Context>> mDisplayContextCache = new SparseArray<>(0);
+
+    /** Only show once automatically in the process life. */
+    private boolean mHasShownHint;
+
+    public SizeCompatModeActivityController() {
+        this(ActivityManagerWrapper.getInstance());
+    }
+
+    @VisibleForTesting
+    SizeCompatModeActivityController(ActivityManagerWrapper am) {
+        am.registerTaskStackListener(new TaskStackChangeListener() {
+            @Override
+            public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
+                // Note the callback already runs on main thread.
+                updateRestartButton(displayId, activityToken);
+            }
+        });
+    }
+
+    @Override
+    public void start() {
+        SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+    }
+
+    @Override
+    public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+            boolean showImeSwitcher) {
+        RestartActivityButton button = mActiveButtons.get(displayId);
+        if (button == null) {
+            return;
+        }
+        boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+        int newVisibility = imeShown ? View.GONE : View.VISIBLE;
+        // Hide the button when input method is showing.
+        if (button.getVisibility() != newVisibility) {
+            button.setVisibility(newVisibility);
+        }
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        mDisplayContextCache.remove(displayId);
+        removeRestartButton(displayId);
+    }
+
+    private void removeRestartButton(int displayId) {
+        RestartActivityButton button = mActiveButtons.get(displayId);
+        if (button != null) {
+            button.remove();
+            mActiveButtons.remove(displayId);
+        }
+    }
+
+    private void updateRestartButton(int displayId, IBinder activityToken) {
+        if (activityToken == null) {
+            // Null token means the current foreground activity is not in size compatibility mode.
+            removeRestartButton(displayId);
+            return;
+        }
+
+        RestartActivityButton restartButton = mActiveButtons.get(displayId);
+        if (restartButton != null) {
+            restartButton.updateLastTargetActivity(activityToken);
+            return;
+        }
+
+        Context context = getOrCreateDisplayContext(displayId);
+        if (context == null) {
+            Log.i(TAG, "Cannot get context for display " + displayId);
+            return;
+        }
+
+        restartButton = createRestartButton(context);
+        restartButton.updateLastTargetActivity(activityToken);
+        restartButton.show();
+        mActiveButtons.append(displayId, restartButton);
+    }
+
+    @VisibleForTesting
+    RestartActivityButton createRestartButton(Context context) {
+        RestartActivityButton button = new RestartActivityButton(context, mHasShownHint);
+        mHasShownHint = true;
+        return button;
+    }
+
+    private Context getOrCreateDisplayContext(int displayId) {
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            return mContext;
+        }
+        Context context = null;
+        WeakReference<Context> ref = mDisplayContextCache.get(displayId);
+        if (ref != null) {
+            context = ref.get();
+        }
+        if (context == null) {
+            Display display = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
+            if (display != null) {
+                context = mContext.createDisplayContext(display);
+                mDisplayContextCache.put(displayId, new WeakReference<Context>(context));
+            }
+        }
+        return context;
+    }
+
+    @VisibleForTesting
+    static class RestartActivityButton extends ImageButton implements View.OnClickListener,
+            View.OnLongClickListener {
+
+        final WindowManager.LayoutParams mWinParams;
+        final boolean mShouldShowHint;
+        IBinder mLastActivityToken;
+
+        final int mPopupOffsetX;
+        final int mPopupOffsetY;
+        PopupWindow mShowingHint;
+
+        RestartActivityButton(Context context, boolean hasShownHint) {
+            super(context);
+            mShouldShowHint = !hasShownHint;
+            Drawable drawable = context.getDrawable(R.drawable.btn_restart);
+            setImageDrawable(drawable);
+            setContentDescription(context.getString(R.string.restart_button_description));
+
+            int drawableW = drawable.getIntrinsicWidth();
+            int drawableH = drawable.getIntrinsicHeight();
+            mPopupOffsetX = drawableW / 2;
+            mPopupOffsetY = drawableH * 2;
+
+            ColorStateList color = ColorStateList.valueOf(Color.LTGRAY);
+            GradientDrawable mask = new GradientDrawable();
+            mask.setShape(GradientDrawable.OVAL);
+            mask.setColor(color);
+            setBackground(new RippleDrawable(color, null /* content */, mask));
+            setOnClickListener(this);
+            setOnLongClickListener(this);
+
+            mWinParams = new WindowManager.LayoutParams();
+            mWinParams.gravity = getGravity(getResources().getConfiguration().getLayoutDirection());
+            mWinParams.width = drawableW * 2;
+            mWinParams.height = drawableH * 2;
+            mWinParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+            mWinParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+            mWinParams.format = PixelFormat.TRANSLUCENT;
+            mWinParams.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            mWinParams.setTitle(SizeCompatModeActivityController.class.getSimpleName()
+                    + context.getDisplayId());
+        }
+
+        void updateLastTargetActivity(IBinder activityToken) {
+            mLastActivityToken = activityToken;
+        }
+
+        void show() {
+            getContext().getSystemService(WindowManager.class).addView(this, mWinParams);
+        }
+
+        void remove() {
+            getContext().getSystemService(WindowManager.class).removeViewImmediate(this);
+        }
+
+        @Override
+        public void onClick(View v) {
+            try {
+                ActivityTaskManager.getService().restartActivityProcessIfVisible(
+                        mLastActivityToken);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Unable to restart activity", e);
+            }
+        }
+
+        @Override
+        public boolean onLongClick(View v) {
+            showHint();
+            return true;
+        }
+
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            if (mShouldShowHint) {
+                showHint();
+            }
+        }
+
+        @Override
+        public void setLayoutDirection(int layoutDirection) {
+            int gravity = getGravity(layoutDirection);
+            if (mWinParams.gravity != gravity) {
+                mWinParams.gravity = gravity;
+                if (mShowingHint != null) {
+                    mShowingHint.dismiss();
+                    showHint();
+                }
+                getContext().getSystemService(WindowManager.class).updateViewLayout(this,
+                        mWinParams);
+            }
+            super.setLayoutDirection(layoutDirection);
+        }
+
+        void showHint() {
+            if (mShowingHint != null) {
+                return;
+            }
+
+            View popupView = LayoutInflater.from(getContext()).inflate(
+                    R.layout.size_compat_mode_hint, null /* root */);
+            PopupWindow popupWindow = new PopupWindow(popupView,
+                    LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+            popupWindow.setElevation(getResources().getDimension(R.dimen.bubble_elevation));
+            popupWindow.setAnimationStyle(android.R.style.Animation_InputMethod);
+            popupWindow.setClippingEnabled(false);
+            popupWindow.setOnDismissListener(() -> mShowingHint = null);
+            mShowingHint = popupWindow;
+
+            Button gotItButton = popupView.findViewById(R.id.got_it);
+            gotItButton.setBackground(new RippleDrawable(ColorStateList.valueOf(Color.LTGRAY),
+                    null /* content */, null /* mask */));
+            gotItButton.setOnClickListener(view -> popupWindow.dismiss());
+            popupWindow.showAtLocation(this, mWinParams.gravity, mPopupOffsetX, mPopupOffsetY);
+        }
+
+        private static int getGravity(int layoutDirection) {
+            return Gravity.BOTTOM
+                    | (layoutDirection == View.LAYOUT_DIRECTION_RTL ? Gravity.START : Gravity.END);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 471619e..03e453f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -95,6 +95,9 @@
     /** Flag to position the header below the activity view */
     private static final String ENABLE_BUBBLE_FOOTER = "experiment_enable_bubble_footer";
 
+    private static final String BUBBLE_STIFFNESS = "experiment_bubble_stiffness";
+    private static final String BUBBLE_BOUNCINESS = "experiment_bubble_bounciness";
+
     private final Context mContext;
     private final NotificationEntryManager mNotificationEntryManager;
     private final IActivityTaskManager mActivityTaskManager;
@@ -569,6 +572,20 @@
                 ENABLE_BUBBLE_FOOTER, 0) != 0;
     }
 
+    /** Default stiffness to use for bubble physics animations. */
+    public static int getBubbleStiffness(Context context, int defaultStiffness) {
+        return Settings.Secure.getInt(
+                context.getContentResolver(), BUBBLE_STIFFNESS, defaultStiffness);
+    }
+
+    /** Default bounciness/damping ratio to use for bubble physics animations. */
+    public static float getBubbleBounciness(Context context, float defaultBounciness) {
+        return Settings.Secure.getInt(
+                context.getContentResolver(),
+                BUBBLE_BOUNCINESS,
+                (int) (defaultBounciness * 100)) / 100f;
+    }
+
     /** PinnedStackListener that dispatches IME visibility updates to the stack. */
     private class BubblesImeListener extends IPinnedStackListener.Stub {
 
@@ -582,12 +599,9 @@
                 int displayRotation) throws RemoteException {}
 
         @Override
-        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight)
-                throws RemoteException {
-            if (mStackView != null) {
-                mStackView.post(() -> {
-                    mStackView.onImeVisibilityChanged(imeVisible, imeHeight);
-                });
+        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+            if (mStackView != null && mStackView.getBubbleCount() > 0) {
+                mStackView.post(() -> mStackView.onImeVisibilityChanged(imeVisible, imeHeight));
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 8235d8d..4869485 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -26,6 +26,7 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.util.StatsLog;
@@ -36,6 +37,7 @@
 import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 
 import androidx.annotation.MainThread;
@@ -205,11 +207,16 @@
                         .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
 
         setClipChildren(false);
-
+        setFocusable(true);
         mBubbleContainer.bringToFront();
     }
 
     @Override
+    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+        getBoundsOnScreen(outRect);
+    }
+
+    @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         getViewTreeObserver().removeOnPreDrawListener(mViewUpdater);
@@ -227,6 +234,36 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfoInternal(info);
+        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
+        if (mIsExpanded) {
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
+        } else {
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_DISMISS:
+                stackDismissed();
+                return true;
+            case AccessibilityNodeInfo.ACTION_COLLAPSE:
+                collapseStack();
+                return true;
+            case AccessibilityNodeInfo.ACTION_EXPAND:
+                expandStack();
+                return true;
+        }
+        return false;
+    }
+
     /**
      * Updates the visibility of the 'dot' indicating an update on the bubble.
      * @param key the {@link NotificationEntry#key} associated with the bubble.
@@ -491,7 +528,9 @@
             if (shouldExpand) {
                 mBubbleContainer.setController(mExpandedAnimationController);
                 mExpandedAnimationController.expandFromStack(
-                        mStackAnimationController.getStackPosition(),
+                        /* collapseTo */
+                        mStackAnimationController.getStackPositionAlongNearestHorizontalEdge(),
+                        /* after */
                         () -> {
                             updatePointerPosition();
                             updateAfter.run();
@@ -719,7 +758,9 @@
     @Override
     public void getBoundsOnScreen(Rect outRect) {
         if (!mIsExpanded) {
-            mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
+            if (mBubbleContainer.getChildCount() > 0) {
+                mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
+            }
         } else {
             mBubbleContainer.getBoundsOnScreen(outRect);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index f7896b0..1f29883 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -49,11 +49,8 @@
     /** How much to scale down bubbles when they're animating in/out. */
     private static final float ANIMATE_SCALE_PERCENT = 0.5f;
 
-    /**
-     * The stack position from which the bubbles were expanded. Saved in {@link #expandFromStack}
-     * and used to return to stack form in {@link #collapseBackToStack}.
-     */
-    private PointF mExpandedFrom;
+    /** The stack position to collapse back to in {@link #collapseBackToStack}. */
+    private PointF mCollapseToPoint;
 
     /** Horizontal offset between bubbles, which we need to know to re-stack them. */
     private float mStackOffsetPx;
@@ -106,8 +103,8 @@
      *
      * @return The y-value to which the bubbles were expanded, in case that's useful.
      */
-    public float expandFromStack(PointF expandedFrom, Runnable after) {
-        mExpandedFrom = expandedFrom;
+    public float expandFromStack(PointF collapseTo, Runnable after) {
+        mCollapseToPoint = collapseTo;
 
         // How much to translate the next bubble, so that it is not overlapping the previous one.
         float translateNextBubbleXBy = mBubblePaddingPx;
@@ -123,10 +120,11 @@
     /** Animate collapsing the bubbles back to their stacked position. */
     public void collapseBackToStack(Runnable after) {
         // Stack to the left if we're going to the left, or right if not.
-        final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mExpandedFrom.x) ? -1 : 1;
+        final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapseToPoint.x) ? -1 : 1;
         for (int i = 0; i < mLayout.getChildCount(); i++) {
             mLayout.animatePositionForChildAtIndex(
-                    i, mExpandedFrom.x + (sideMultiplier * i * mStackOffsetPx), mExpandedFrom.y);
+                    i,
+                    mCollapseToPoint.x + (sideMultiplier * i * mStackOffsetPx), mCollapseToPoint.y);
         }
 
         runAfterTranslationsEnd(after);
@@ -268,8 +266,8 @@
     @Override
     SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
         return new SpringForce()
-                .setStiffness(SpringForce.STIFFNESS_LOW)
-                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+                .setStiffness(SpringForce.STIFFNESS_LOW);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index f47fbe0..af5035b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -30,6 +30,7 @@
 import androidx.dynamicanimation.animation.SpringForce;
 
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleController;
 
 import com.google.android.collect.Sets;
 
@@ -134,6 +135,18 @@
     }
 
     /**
+     * Where the stack would be if it were snapped to the nearest horizontal edge (left or right).
+     */
+    public PointF getStackPositionAlongNearestHorizontalEdge() {
+        final PointF stackPos = getStackPosition();
+        final boolean onLeft = mLayout.isFirstChildXLeftOfCenter(stackPos.x);
+        final RectF bounds = getAllowableStackPositionRegion();
+
+        stackPos.x = onLeft ? bounds.left : bounds.right;
+        return stackPos;
+    }
+
+    /**
      * Flings the first bubble along the given property's axis, using the provided configuration
      * values. When the animation ends - either by hitting the min/max, or by friction sufficiently
      * reducing momentum - a SpringAnimation takes over to snap the bubble to the given final
@@ -325,8 +338,10 @@
     @Override
     SpringForce getSpringForce(DynamicAnimation.ViewProperty property, View view) {
         return new SpringForce()
-                .setDampingRatio(DEFAULT_BOUNCINESS)
-                .setStiffness(DEFAULT_STIFFNESS);
+                .setDampingRatio(BubbleController.getBubbleBounciness(
+                        mLayout.getContext(), DEFAULT_BOUNCINESS))
+                .setStiffness(BubbleController.getBubbleStiffness(
+                        mLayout.getContext(), (int) (DEFAULT_STIFFNESS * 100f)));
     }
 
     @Override
@@ -440,6 +455,10 @@
             DynamicAnimation.ViewProperty property, SpringForce spring,
             float vel, float finalPosition) {
 
+        if (mLayout.getChildCount() == 0) {
+            return;
+        }
+
         Log.d(TAG, String.format("Springing %s to final position %f.",
                 PhysicsAnimationLayout.getReadablePropertyName(property),
                 finalPosition));
@@ -489,7 +508,7 @@
 
         @Override
         public float getValue(StackAnimationController controller) {
-            return mProperty.getValue(mLayout.getChildAt(0));
+            return mLayout.getChildCount() > 0 ? mProperty.getValue(mLayout.getChildAt(0)) : 0;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 7656564..c3d4b0f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -39,6 +39,7 @@
  */
 public class DozeUi implements DozeMachine.Part {
 
+    private static final String TAG = "DozeUi";
     private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
     private final Context mContext;
     private final DozeHost mHost;
@@ -93,6 +94,10 @@
                 new DozeHost.PulseCallback() {
                     @Override
                     public void onPulseStarted() {
+                        if (mMachine.getState() != DozeMachine.State.DOZE_REQUEST_PULSE) {
+                            Log.w(TAG, "Pulse was cancelled before it could have been started");
+                            return;
+                        }
                         mMachine.requestState(DozeMachine.State.DOZE_PULSING);
                     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3fa6035..1f3762d 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -67,6 +67,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
@@ -88,14 +89,17 @@
 import com.android.systemui.MultiListLayout;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
-import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.plugins.GlobalActionsPanelPlugin;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 import com.android.systemui.util.EmergencyDialerConstants;
 import com.android.systemui.util.leak.RotationUtils;
 import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Helper to show the global actions dialog.  Each item is an {@link Action} that
@@ -160,6 +164,8 @@
     private final ScreenshotHelper mScreenshotHelper;
     private final ScreenRecordHelper mScreenRecordHelper;
 
+    private final Extension<GlobalActionsPanelPlugin> mPanelExtension;
+
     /**
      * @param context everything needs a context :(
      */
@@ -203,6 +209,11 @@
         mScreenRecordHelper = new ScreenRecordHelper(context);
 
         Dependency.get(ConfigurationController.class).addCallback(this);
+
+        mPanelExtension = Dependency.get(ExtensionController.class)
+            .newExtension(GlobalActionsPanelPlugin.class)
+            .withPlugin(GlobalActionsPanelPlugin.class)
+            .build();
     }
 
     /**
@@ -398,8 +409,16 @@
             }
             return false;
         };
+        GlobalActionsPanelPlugin.PanelViewController panelViewController =
+                mPanelExtension.get() != null
+                        ? mPanelExtension.get().onPanelShown(() -> {
+                            if (mDialog != null) {
+                                mDialog.dismiss();
+                            }
+                        })
+                        : null;
         ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener,
-                mSeparatedEmergencyButtonEnabled);
+                mSeparatedEmergencyButtonEnabled, panelViewController);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setKeyguardShowing(mKeyguardShowing);
 
@@ -474,7 +493,9 @@
         public void onPress() {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
             Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
                     EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -1469,20 +1490,22 @@
         private MultiListLayout mGlobalActionsLayout;
         private final OnClickListener mClickListener;
         private final OnItemLongClickListener mLongClickListener;
-        private final GradientDrawable mGradientDrawable;
+        private final Drawable mBackgroundDrawable;
         private final ColorExtractor mColorExtractor;
+        private final GlobalActionsPanelPlugin.PanelViewController mPanelController;
         private boolean mKeyguardShowing;
         private boolean mShouldDisplaySeparatedButton;
         private boolean mShowing;
+        private final float mScrimAlpha;
 
         public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
-                OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton) {
+                OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton,
+                GlobalActionsPanelPlugin.PanelViewController plugin) {
             super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = context;
             mAdapter = adapter;
             mClickListener = clickListener;
             mLongClickListener = longClickListener;
-            mGradientDrawable = new GradientDrawable(mContext);
             mColorExtractor = Dependency.get(SysuiColorExtractor.class);
             mShouldDisplaySeparatedButton = shouldDisplaySeparatedButton;
 
@@ -1503,12 +1526,46 @@
                     | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                     | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
-            window.setBackgroundDrawable(mGradientDrawable);
             window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
 
             initializeLayout();
 
             setTitle(R.string.global_actions);
+
+            mPanelController = plugin;
+            View panelView = initializePanel();
+            if (panelView == null) {
+                mBackgroundDrawable = new GradientDrawable(context);
+                mScrimAlpha = 0.7f;
+            } else {
+                mBackgroundDrawable = context.getDrawable(
+                        com.android.systemui.R.drawable.global_action_panel_scrim);
+                mScrimAlpha = 1f;
+                addContentView(
+                        panelView,
+                        new ViewGroup.LayoutParams(
+                                ViewGroup.LayoutParams.MATCH_PARENT,
+                                ViewGroup.LayoutParams.MATCH_PARENT));
+            }
+            window.setBackgroundDrawable(mBackgroundDrawable);
+        }
+
+        private View initializePanel() {
+            if (isPanelEnabled(mContext) && mPanelController != null) {
+                View panelView = mPanelController.getPanelContent();
+                if (panelView != null) {
+                    FrameLayout panelContainer = new FrameLayout(mContext);
+                    FrameLayout.LayoutParams panelParams =
+                            new FrameLayout.LayoutParams(
+                                    FrameLayout.LayoutParams.MATCH_PARENT,
+                                    FrameLayout.LayoutParams.WRAP_CONTENT);
+                    panelParams.topMargin = mContext.getResources().getDimensionPixelSize(
+                            com.android.systemui.R.dimen.global_actions_panel_top_margin);
+                    panelContainer.addView(panelView, panelParams);
+                    return panelContainer;
+                }
+            }
+            return null;
         }
 
         private void initializeLayout() {
@@ -1529,6 +1586,11 @@
             mGlobalActionsLayout.setRotationListener(this::onRotate);
         }
 
+        private boolean isPanelEnabled(Context context) {
+            return FeatureFlagUtils.isEnabled(
+                    context, FeatureFlagUtils.GLOBAL_ACTIONS_PANEL_ENABLED);
+        }
+
         private int getGlobalActionsLayoutId(Context context) {
             if (isGridEnabled(context)) {
                 if (RotationUtils.getRotation(context) == RotationUtils.ROTATION_SEASCAPE) {
@@ -1546,33 +1608,40 @@
             ArrayList<Action> listActions = mAdapter.getListActions(mShouldDisplaySeparatedButton);
             mGlobalActionsLayout.setExpectedListItemCount(listActions.size());
             mGlobalActionsLayout.setExpectedSeparatedItemCount(separatedActions.size());
+            int rotation = RotationUtils.getRotation(mContext);
+
+            boolean reverse = false; // should we add items to parents in the reverse order?
+            if (isGridEnabled(mContext)) {
+                if (rotation == RotationUtils.ROTATION_NONE
+                        || rotation == RotationUtils.ROTATION_SEASCAPE) {
+                    reverse = !reverse; // if we're in portrait or seascape, reverse items
+                }
+                if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+                        == View.LAYOUT_DIRECTION_RTL) {
+                    reverse = !reverse; // if we're in an RTL language, reverse items (again)
+                }
+            }
 
             for (int i = 0; i < mAdapter.getCount(); i++) {
                 Action action = mAdapter.getItem(i);
                 int separatedIndex = separatedActions.indexOf(action);
                 ViewGroup parent;
                 if (separatedIndex != -1) {
-                    parent = mGlobalActionsLayout.getParentView(true, separatedIndex, false);
+                    parent = mGlobalActionsLayout.getParentView(true, separatedIndex, rotation);
                 } else {
-                    boolean reverse = false;
-
-                    // If we're using the grid layout and we're in seascape, reverse the order
-                    // of sublists to make sure they render in the correct positions,
-                    // since we can't reverse vertical LinearLayouts through the layout xml.
-
-                    if (isGridEnabled(mContext) && RotationUtils.getRotation(mContext)
-                            == RotationUtils.ROTATION_SEASCAPE) {
-                        reverse = true;
-                    }
                     int listIndex = listActions.indexOf(action);
-                    parent = mGlobalActionsLayout.getParentView(false, listIndex, reverse);
+                    parent = mGlobalActionsLayout.getParentView(false, listIndex, rotation);
                 }
                 View v = mAdapter.getView(i, null, parent);
                 final int pos = i;
                 v.setOnClickListener(view -> mClickListener.onClick(this, pos));
                 v.setOnLongClickListener(view ->
                         mLongClickListener.onItemLongClick(null, v, pos, 0));
-                parent.addView(v);
+                if (reverse) {
+                    parent.addView(v, 0); // reverse order of items
+                } else {
+                    parent.addView(v);
+                }
             }
         }
 
@@ -1582,13 +1651,18 @@
             super.onStart();
             updateList();
 
-            Point displaySize = new Point();
-            mContext.getDisplay().getRealSize(displaySize);
-            mColorExtractor.addOnColorsChangedListener(this);
-            mGradientDrawable.setScreenSize(displaySize.x, displaySize.y);
-            GradientColors colors = mColorExtractor.getColors(mKeyguardShowing ?
-                    WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
-            updateColors(colors, false /* animate */);
+            if (mBackgroundDrawable instanceof GradientDrawable) {
+                Point displaySize = new Point();
+                mContext.getDisplay().getRealSize(displaySize);
+                mColorExtractor.addOnColorsChangedListener(this);
+                ((GradientDrawable) mBackgroundDrawable)
+                        .setScreenSize(displaySize.x, displaySize.y);
+                GradientColors colors = mColorExtractor.getColors(
+                        mKeyguardShowing
+                                ? WallpaperManager.FLAG_LOCK
+                                : WallpaperManager.FLAG_SYSTEM);
+                updateColors(colors, false /* animate */);
+            }
         }
 
         /**
@@ -1597,11 +1671,14 @@
          * @param animate Interpolates gradient if true, just sets otherwise.
          */
         private void updateColors(GradientColors colors, boolean animate) {
-            mGradientDrawable.setColors(colors, animate);
+            if (!(mBackgroundDrawable instanceof GradientDrawable)) {
+                return;
+            }
+            ((GradientDrawable) mBackgroundDrawable).setColors(colors, animate);
             View decorView = getWindow().getDecorView();
             if (colors.supportsDarkText()) {
                 decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
-                    View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+                        View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
             } else {
                 decorView.setSystemUiVisibility(0);
             }
@@ -1617,7 +1694,7 @@
         public void show() {
             super.show();
             mShowing = true;
-            mGradientDrawable.setAlpha(0);
+            mBackgroundDrawable.setAlpha(0);
             mGlobalActionsLayout.setTranslationX(getAnimTranslation());
             mGlobalActionsLayout.setAlpha(0);
             mGlobalActionsLayout.animate()
@@ -1627,8 +1704,8 @@
                     .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                     .setUpdateListener(animation -> {
                         int alpha = (int) ((Float) animation.getAnimatedValue()
-                                * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
-                        mGradientDrawable.setAlpha(alpha);
+                                * mScrimAlpha * 255);
+                        mBackgroundDrawable.setAlpha(alpha);
                     })
                     .start();
         }
@@ -1645,14 +1722,17 @@
                     .alpha(0)
                     .translationX(getAnimTranslation())
                     .setDuration(300)
-                    .withEndAction(() -> super.dismiss())
+                    .withEndAction(super::dismiss)
                     .setInterpolator(new LogAccelerateInterpolator())
                     .setUpdateListener(animation -> {
                         int alpha = (int) ((1f - (Float) animation.getAnimatedValue())
-                                * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
-                        mGradientDrawable.setAlpha(alpha);
+                                * mScrimAlpha * 255);
+                        mBackgroundDrawable.setAlpha(alpha);
                     })
                     .start();
+            if (mPanelController != null) {
+                mPanelController.onDismissed();
+            }
         }
 
         void dismissImmediately() {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index 1d04277..036d8ca 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -23,6 +23,7 @@
 
 import com.android.systemui.HardwareBgDrawable;
 import com.android.systemui.MultiListLayout;
+import com.android.systemui.util.leak.RotationUtils;
 
 /**
  * Grid-based implementation of the button layout created by the global actions dialog.
@@ -83,11 +84,18 @@
     }
 
     @Override
-    public ViewGroup getParentView(boolean separated, int index, boolean reverseOrder) {
+    public ViewGroup getParentView(boolean separated, int index, int rotation) {
         if (separated) {
             return getSeparatedView();
         } else {
-            return getListView().getParentView(index, reverseOrder);
+            switch (rotation) {
+                case RotationUtils.ROTATION_LANDSCAPE:
+                    return getListView().getParentView(index, false, true);
+                case RotationUtils.ROTATION_SEASCAPE:
+                    return getListView().getParentView(index, true, true);
+                default:
+                    return getListView().getParentView(index, false, false);
+            }
         }
     }
 
@@ -96,6 +104,6 @@
      */
     @Override
     public void setDivisionView(View v) {
-
+        // do nothing
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
index d5dcd74..4df1c5a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
@@ -62,11 +62,11 @@
     /**
      * Get the parent view associated with the item which should be placed at the given position.
      */
-    public ViewGroup getParentView(int index, boolean reverseSublists) {
+    public ViewGroup getParentView(int index, boolean reverseSublists, boolean swapRowsAndColumns) {
         if (mRows == 0) {
             return null;
         }
-        int column = getParentViewIndex(index, reverseSublists);
+        int column = getParentViewIndex(index, reverseSublists, swapRowsAndColumns);
         return (ViewGroup) getChildAt(column);
     }
 
@@ -74,13 +74,18 @@
         return getChildCount() - (index + 1);
     }
 
-    private int getParentViewIndex(int index, boolean reverseSublists) {
-        int column = (int) Math.floor(index / mRows);
-        int columnCount = getChildCount();
-        if (reverseSublists) {
-            column = reverseSublistIndex(column);
+    private int getParentViewIndex(int index, boolean reverseSublists, boolean swapRowsAndColumns) {
+        int sublistIndex;
+        ViewGroup row;
+        if (swapRowsAndColumns) {
+            sublistIndex = (int) Math.floor(index / mRows);
+        } else {
+            sublistIndex = index % mRows;
         }
-        return column;
+        if (reverseSublists) {
+            sublistIndex = reverseSublistIndex(sublistIndex);
+        }
+        return sublistIndex;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
index 19d85b1..a313336 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -50,7 +50,7 @@
 
     static final String A_POSITION = "aPosition";
     static final String A_TEXTURE_COORDINATES = "aTextureCoordinates";
-    static final String U_CENTER_REVEAL = "uCenterReveal";
+    static final String U_PER85 = "uPer85";
     static final String U_REVEAL = "uReveal";
     static final String U_AOD2OPACITY = "uAod2Opacity";
     static final String U_TEXTURE = "uTexture";
@@ -87,7 +87,7 @@
     private int mAttrPosition;
     private int mAttrTextureCoordinates;
     private int mUniAod2Opacity;
-    private int mUniCenterReveal;
+    private int mUniPer85;
     private int mUniReveal;
     private int mUniTexture;
     private int mTextureId;
@@ -131,7 +131,7 @@
 
     private void setupUniforms() {
         mUniAod2Opacity = mProgram.getUniformHandle(U_AOD2OPACITY);
-        mUniCenterReveal = mProgram.getUniformHandle(U_CENTER_REVEAL);
+        mUniPer85 = mProgram.getUniformHandle(U_PER85);
         mUniReveal = mProgram.getUniformHandle(U_REVEAL);
         mUniTexture = mProgram.getUniformHandle(U_TEXTURE);
     }
@@ -144,8 +144,8 @@
                 return mAttrTextureCoordinates;
             case U_AOD2OPACITY:
                 return mUniAod2Opacity;
-            case U_CENTER_REVEAL:
-                return mUniCenterReveal;
+            case U_PER85:
+                return mUniPer85;
             case U_REVEAL:
                 return mUniReveal;
             case U_TEXTURE:
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 991b116..7295008 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -93,13 +93,13 @@
 
     @Override
     public void onDrawFrame(GL10 gl) {
-        float threshold = mImageProcessHelper.getPercentile85();
+        float per85 = mImageProcessHelper.getPercentile85();
         float reveal = mImageRevealHelper.getReveal();
 
         glClear(GL_COLOR_BUFFER_BIT);
 
         glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
-        glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_CENTER_REVEAL), threshold);
+        glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), per85);
         glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
 
         mWallpaper.useTexture();
diff --git a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
new file mode 100644
index 0000000..d7a2d9a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
@@ -0,0 +1,55 @@
+package com.android.systemui.power
+
+import com.android.systemui.power.PowerUI.NO_ESTIMATE_AVAILABLE
+
+/**
+ * A simple data class to snapshot battery state when a particular check for the
+ * low battery warning is running in the background.
+ */
+data class BatteryStateSnapshot(
+    val batteryLevel: Int,
+    val isPowerSaver: Boolean,
+    val plugged: Boolean,
+    val bucket: Int,
+    val batteryStatus: Int,
+    val severeLevelThreshold: Int,
+    val lowLevelThreshold: Int,
+    val timeRemainingMillis: Long,
+    val severeThresholdMillis: Long,
+    val lowThresholdMillis: Long,
+    val isBasedOnUsage: Boolean
+) {
+    /**
+     * Returns whether hybrid warning logic/copy should be used for this snapshot
+     */
+    var isHybrid: Boolean = false
+        private set
+
+    init {
+        this.isHybrid = true
+    }
+
+    constructor(
+        batteryLevel: Int,
+        isPowerSaver: Boolean,
+        plugged: Boolean,
+        bucket: Int,
+        batteryStatus: Int,
+        severeLevelThreshold: Int,
+        lowLevelThreshold: Int
+    ) : this(
+        batteryLevel,
+        isPowerSaver,
+        plugged,
+        bucket,
+        batteryStatus,
+        severeLevelThreshold,
+        lowLevelThreshold,
+        NO_ESTIMATE_AVAILABLE.toLong(),
+        NO_ESTIMATE_AVAILABLE.toLong(),
+        NO_ESTIMATE_AVAILABLE.toLong(),
+        false
+    ) {
+        this.isHybrid = false
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/Estimate.java b/packages/SystemUI/src/com/android/systemui/power/Estimate.java
deleted file mode 100644
index 12a8f0a..0000000
--- a/packages/SystemUI/src/com/android/systemui/power/Estimate.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.android.systemui.power;
-
-public class Estimate {
-    public final long estimateMillis;
-    public final boolean isBasedOnUsage;
-
-    public Estimate(long estimateMillis, boolean isBasedOnUsage) {
-        this.estimateMillis = estimateMillis;
-        this.isBasedOnUsage = isBasedOnUsage;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/power/Estimate.kt b/packages/SystemUI/src/com/android/systemui/power/Estimate.kt
new file mode 100644
index 0000000..dca0d45
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/Estimate.kt
@@ -0,0 +1,3 @@
+package com.android.systemui.power
+
+data class Estimate(val estimateMillis: Long, val isBasedOnUsage: Boolean)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index fdb0b36..41bcab5 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -134,10 +134,6 @@
     private int mShowing;
 
     private long mWarningTriggerTimeMs;
-
-    private Estimate mEstimate;
-    private long mLowWarningThreshold;
-    private long mSevereWarningThreshold;
     private boolean mWarning;
     private boolean mShowAutoSaverSuggestion;
     private boolean mPlaySound;
@@ -148,6 +144,7 @@
     private SystemUIDialog mHighTempDialog;
     private SystemUIDialog mThermalShutdownDialog;
     @VisibleForTesting SystemUIDialog mUsbHighTempDialog;
+    private BatteryStateSnapshot mCurrentBatterySnapshot;
 
     /**
      */
@@ -195,17 +192,8 @@
     }
 
     @Override
-    public void updateEstimate(Estimate estimate) {
-        mEstimate = estimate;
-        if (estimate.estimateMillis <= mLowWarningThreshold) {
-            mWarningTriggerTimeMs = System.currentTimeMillis();
-        }
-    }
-
-    @Override
-    public void updateThresholds(long lowThreshold, long severeThreshold) {
-        mLowWarningThreshold = lowThreshold;
-        mSevereWarningThreshold = severeThreshold;
+    public void updateSnapshot(BatteryStateSnapshot snapshot) {
+        mCurrentBatterySnapshot = snapshot;
     }
 
     private void updateNotification() {
@@ -254,15 +242,17 @@
 
     protected void showWarningNotification() {
         final String percentage = NumberFormat.getPercentInstance()
-                .format((double) mBatteryLevel / 100.0);
+                .format((double) mCurrentBatterySnapshot.getBatteryLevel() / 100.0);
 
-        // get standard notification copy
+        // get shared standard notification copy
         String title = mContext.getString(R.string.battery_low_title);
-        String contentText = mContext.getString(R.string.battery_low_percent_format, percentage);
+        String contentText;
 
-        // override notification copy if hybrid notification enabled
-        if (mEstimate != null) {
+        // get correct content text if notification is hybrid or not
+        if (mCurrentBatterySnapshot.isHybrid()) {
             contentText = getHybridContentString(percentage);
+        } else {
+            contentText = mContext.getString(R.string.battery_low_percent_format, percentage);
         }
 
         final Notification.Builder nb =
@@ -282,8 +272,9 @@
         }
         // Make the notification red if the percentage goes below a certain amount or the time
         // remaining estimate is disabled
-        if (mEstimate == null || mBucket < 0
-                || mEstimate.estimateMillis < mSevereWarningThreshold) {
+        if (!mCurrentBatterySnapshot.isHybrid() || mBucket < 0
+                || mCurrentBatterySnapshot.getTimeRemainingMillis()
+                        < mCurrentBatterySnapshot.getSevereThresholdMillis()) {
             nb.setColor(Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorError));
         }
 
@@ -324,10 +315,10 @@
 
     private String getHybridContentString(String percentage) {
         return PowerUtil.getBatteryRemainingStringFormatted(
-            mContext,
-            mEstimate.estimateMillis,
-            percentage,
-            mEstimate.isBasedOnUsage);
+                mContext,
+                mCurrentBatterySnapshot.getTimeRemainingMillis(),
+                percentage,
+                mCurrentBatterySnapshot.isBasedOnUsage());
     }
 
     private PendingIntent pendingBroadcast(String action) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index e27c25e..1863860 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -55,6 +55,7 @@
 import java.util.concurrent.Future;
 
 public class PowerUI extends SystemUI {
+
     static final String TAG = "PowerUI";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final long TEMPERATURE_INTERVAL = 30 * DateUtils.SECOND_IN_MILLIS;
@@ -63,6 +64,7 @@
     static final long THREE_HOURS_IN_MILLIS = DateUtils.HOUR_IN_MILLIS * 3;
     private static final int CHARGE_CYCLE_PERCENT_RESET = 45;
     private static final long SIX_HOURS_MILLIS = Duration.ofHours(6).toMillis();
+    public static final int NO_ESTIMATE_AVAILABLE = -1;
 
     private final Handler mHandler = new Handler();
     @VisibleForTesting
@@ -71,13 +73,9 @@
     private PowerManager mPowerManager;
     private WarningsUI mWarnings;
     private final Configuration mLastConfiguration = new Configuration();
-    private long mTimeRemaining = Long.MAX_VALUE;
     private int mPlugType = 0;
     private int mInvalidCharger = 0;
     private EnhancedEstimates mEnhancedEstimates;
-    private Estimate mLastEstimate;
-    private boolean mLowWarningShownThisChargeCycle;
-    private boolean mSevereWarningShownThisChargeCycle;
     private Future mLastShowWarningTask;
     private boolean mEnableSkinTemperatureWarning;
     private boolean mEnableUsbTemperatureAlarm;
@@ -87,6 +85,10 @@
 
     private long mScreenOffTime = -1;
 
+    @VisibleForTesting boolean mLowWarningShownThisChargeCycle;
+    @VisibleForTesting boolean mSevereWarningShownThisChargeCycle;
+    @VisibleForTesting BatteryStateSnapshot mCurrentBatteryStateSnapshot;
+    @VisibleForTesting BatteryStateSnapshot mLastBatteryStateSnapshot;
     @VisibleForTesting IThermalService mThermalService;
 
     @VisibleForTesting int mBatteryLevel = 100;
@@ -205,6 +207,7 @@
                 mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
                 final int oldInvalidCharger = mInvalidCharger;
                 mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
+                mLastBatteryStateSnapshot = mCurrentBatteryStateSnapshot;
 
                 final boolean plugged = mPlugType != 0;
                 final boolean oldPlugged = oldPlugType != 0;
@@ -233,16 +236,22 @@
                     mWarnings.dismissInvalidChargerWarning();
                 } else if (mWarnings.isInvalidChargerWarningShowing()) {
                     // if invalid charger is showing, don't show low battery
+                    if (DEBUG) {
+                        Slog.d(TAG, "Bad Charger");
+                    }
                     return;
                 }
 
                 // Show the correct version of low battery warning if needed
                 if (mLastShowWarningTask != null) {
                     mLastShowWarningTask.cancel(true);
+                    if (DEBUG) {
+                        Slog.d(TAG, "cancelled task");
+                    }
                 }
                 mLastShowWarningTask = ThreadUtils.postOnBackgroundThread(() -> {
-                    maybeShowBatteryWarning(
-                            oldBatteryLevel, plugged, oldPlugged, oldBucket, bucket);
+                    maybeShowBatteryWarningV2(
+                            plugged, bucket);
                 });
 
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
@@ -257,53 +266,150 @@
         }
     }
 
-    protected void maybeShowBatteryWarning(int oldBatteryLevel, boolean plugged, boolean oldPlugged,
-            int oldBucket, int bucket) {
-        boolean isPowerSaver = mPowerManager.isPowerSaveMode();
-        // only play SFX when the dialog comes up or the bucket changes
-        final boolean playSound = bucket != oldBucket || oldPlugged;
+    protected void maybeShowBatteryWarningV2(boolean plugged, int bucket) {
         final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
-        if (hybridEnabled) {
-            Estimate estimate = mLastEstimate;
-            if (estimate == null || mBatteryLevel != oldBatteryLevel) {
-                estimate = mEnhancedEstimates.getEstimate();
-                mLastEstimate = estimate;
-            }
-            // Turbo is not always booted once SysUI is running so we have to make sure we actually
-            // get data back
-            if (estimate != null) {
-                mTimeRemaining = estimate.estimateMillis;
-                mWarnings.updateEstimate(estimate);
-                mWarnings.updateThresholds(mEnhancedEstimates.getLowWarningThreshold(),
-                        mEnhancedEstimates.getSevereWarningThreshold());
+        final boolean isPowerSaverMode = mPowerManager.isPowerSaveMode();
 
-                // if we are now over 45% battery & 6 hours remaining we can trigger hybrid
-                // notification again
-                if (mBatteryLevel >= CHARGE_CYCLE_PERCENT_RESET
-                        && mTimeRemaining > SIX_HOURS_MILLIS) {
-                    mLowWarningShownThisChargeCycle = false;
-                    mSevereWarningShownThisChargeCycle = false;
-                }
+        // Stick current battery state into an immutable container to determine if we should show
+        // a warning.
+        if (DEBUG) {
+            Slog.d(TAG, "evaluating which notification to show");
+        }
+        if (hybridEnabled) {
+            if (DEBUG) {
+                Slog.d(TAG, "using hybrid");
+            }
+            Estimate estimate = refreshEstimateIfNeeded();
+            mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
+                    plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
+                    mLowBatteryReminderLevels[0], estimate.getEstimateMillis(),
+                    mEnhancedEstimates.getSevereWarningThreshold(),
+                    mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage());
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "using standard");
+            }
+            mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode,
+                    plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1],
+                    mLowBatteryReminderLevels[0]);
+        }
+
+        mWarnings.updateSnapshot(mCurrentBatteryStateSnapshot);
+        if (mCurrentBatteryStateSnapshot.isHybrid()) {
+            maybeShowHybridWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
+        } else {
+            maybeShowBatteryWarning(mCurrentBatteryStateSnapshot, mLastBatteryStateSnapshot);
+        }
+    }
+
+    // updates the time estimate if we don't have one or battery level has changed.
+    @VisibleForTesting
+    Estimate refreshEstimateIfNeeded() {
+        if (mLastBatteryStateSnapshot == null
+                || mLastBatteryStateSnapshot.getTimeRemainingMillis() == NO_ESTIMATE_AVAILABLE
+                || mBatteryLevel != mLastBatteryStateSnapshot.getBatteryLevel()) {
+            final Estimate estimate = mEnhancedEstimates.getEstimate();
+            if (DEBUG) {
+                Slog.d(TAG, "updated estimate: " + estimate.getEstimateMillis());
+            }
+            return estimate;
+        }
+        return new Estimate(mLastBatteryStateSnapshot.getTimeRemainingMillis(),
+                mLastBatteryStateSnapshot.isBasedOnUsage());
+    }
+
+    @VisibleForTesting
+    void maybeShowHybridWarning(BatteryStateSnapshot currentSnapshot,
+            BatteryStateSnapshot lastSnapshot) {
+        // if we are now over 45% battery & 6 hours remaining so we can trigger hybrid
+        // notification again
+        if (currentSnapshot.getBatteryLevel() >= CHARGE_CYCLE_PERCENT_RESET
+                && currentSnapshot.getTimeRemainingMillis() > SIX_HOURS_MILLIS) {
+            mLowWarningShownThisChargeCycle = false;
+            mSevereWarningShownThisChargeCycle = false;
+            if (DEBUG) {
+                Slog.d(TAG, "Charge cycle reset! Can show warnings again");
             }
         }
 
-        if (shouldShowLowBatteryWarning(plugged, oldPlugged, oldBucket, bucket,
-                mTimeRemaining, isPowerSaver, mBatteryStatus)) {
-            mWarnings.showLowBatteryWarning(playSound);
+        final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
+                || lastSnapshot.getPlugged();
 
+        if (shouldShowHybridWarning(currentSnapshot)) {
+            mWarnings.showLowBatteryWarning(playSound);
             // mark if we've already shown a warning this cycle. This will prevent the notification
             // trigger from spamming users by only showing low/critical warnings once per cycle
-            if (hybridEnabled) {
-                if (mTimeRemaining <= mEnhancedEstimates.getSevereWarningThreshold()
-                        || mBatteryLevel <= mLowBatteryReminderLevels[1]) {
-                    mSevereWarningShownThisChargeCycle = true;
-                    mLowWarningShownThisChargeCycle = true;
-                } else {
-                    mLowWarningShownThisChargeCycle = true;
+            if (currentSnapshot.getTimeRemainingMillis()
+                    <= currentSnapshot.getSevereLevelThreshold()
+                    || currentSnapshot.getBatteryLevel() <= mLowBatteryReminderLevels[1]) {
+                mSevereWarningShownThisChargeCycle = true;
+                mLowWarningShownThisChargeCycle = true;
+                if (DEBUG) {
+                    Slog.d(TAG, "Severe warning marked as shown this cycle");
                 }
+            } else {
+                Slog.d(TAG, "Low warning marked as shown this cycle");
+                mLowWarningShownThisChargeCycle = true;
             }
-        } else if (shouldDismissLowBatteryWarning(plugged, oldBucket, bucket, mTimeRemaining,
-                isPowerSaver)) {
+
+        } else if (shouldDismissHybridWarning(currentSnapshot)) {
+            if (DEBUG) {
+                Slog.d(TAG, "Dismissing warning");
+            }
+            mWarnings.dismissLowBatteryWarning();
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "Updating warning");
+            }
+            mWarnings.updateLowBatteryWarning();
+        }
+    }
+
+    @VisibleForTesting
+    boolean shouldShowHybridWarning(BatteryStateSnapshot snapshot) {
+        if (snapshot.getPlugged()
+                || snapshot.getBatteryStatus() == BatteryManager.BATTERY_STATUS_UNKNOWN) {
+            Slog.d(TAG, "can't show warning due to - plugged: " + snapshot.getPlugged()
+                    + " status unknown: "
+                    + (snapshot.getBatteryStatus() == BatteryManager.BATTERY_STATUS_UNKNOWN));
+            return false;
+        }
+
+        // Only show the low warning once per charge cycle & no battery saver
+        final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !snapshot.isPowerSaver()
+                && (snapshot.getTimeRemainingMillis() < snapshot.getLowThresholdMillis()
+                || snapshot.getBatteryLevel() <= snapshot.getLowLevelThreshold());
+
+        // Only show the severe warning once per charge cycle
+        final boolean canShowSevereWarning = !mSevereWarningShownThisChargeCycle
+                && (snapshot.getTimeRemainingMillis() < snapshot.getSevereThresholdMillis()
+                || snapshot.getBatteryLevel() <= snapshot.getSevereLevelThreshold());
+
+        final boolean canShow = canShowWarning || canShowSevereWarning;
+        if (DEBUG) {
+            Slog.d(TAG, "Enhanced trigger is: " + canShow + "\nwith battery snapshot:"
+                    + " mLowWarningShownThisChargeCycle: " + mLowWarningShownThisChargeCycle
+                    + " mSevereWarningShownThisChargeCycle: " + mSevereWarningShownThisChargeCycle
+                    + "\n" + snapshot.toString());
+        }
+        return canShow;
+    }
+
+    @VisibleForTesting
+    boolean shouldDismissHybridWarning(BatteryStateSnapshot snapshot) {
+        return snapshot.getPlugged()
+                || snapshot.getTimeRemainingMillis() > snapshot.getLowThresholdMillis();
+    }
+
+    protected void maybeShowBatteryWarning(
+            BatteryStateSnapshot currentSnapshot,
+            BatteryStateSnapshot lastSnapshot) {
+        final boolean playSound = currentSnapshot.getBucket() != lastSnapshot.getBucket()
+                || lastSnapshot.getPlugged();
+
+        if (shouldShowLowBatteryWarning(currentSnapshot, lastSnapshot)) {
+            mWarnings.showLowBatteryWarning(playSound);
+        } else if (shouldDismissLowBatteryWarning(currentSnapshot, lastSnapshot)) {
             mWarnings.dismissLowBatteryWarning();
         } else {
             mWarnings.updateLowBatteryWarning();
@@ -311,64 +417,25 @@
     }
 
     @VisibleForTesting
-    boolean shouldShowLowBatteryWarning(boolean plugged, boolean oldPlugged, int oldBucket,
-            int bucket, long timeRemaining, boolean isPowerSaver, int batteryStatus) {
-        if (mEnhancedEstimates.isHybridNotificationEnabled()) {
-            // triggering logic when enhanced estimate is available
-            return isEnhancedTrigger(plugged, timeRemaining, isPowerSaver, batteryStatus);
-        }
-        // legacy triggering logic
-        return !plugged
-                && !isPowerSaver
-                && (((bucket < oldBucket || oldPlugged) && bucket < 0))
-                && batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN;
+    boolean shouldShowLowBatteryWarning(
+            BatteryStateSnapshot currentSnapshot,
+            BatteryStateSnapshot lastSnapshot) {
+        return !currentSnapshot.getPlugged()
+                && !currentSnapshot.isPowerSaver()
+                && (((currentSnapshot.getBucket() < lastSnapshot.getBucket()
+                        || lastSnapshot.getPlugged())
+                && currentSnapshot.getBucket() < 0))
+                && currentSnapshot.getBatteryStatus() != BatteryManager.BATTERY_STATUS_UNKNOWN;
     }
 
     @VisibleForTesting
-    boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket,
-            long timeRemaining, boolean isPowerSaver) {
-        final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled();
-        final boolean hybridWouldDismiss = hybridEnabled
-                && timeRemaining > mEnhancedEstimates.getLowWarningThreshold();
-        final boolean standardWouldDismiss = (bucket > oldBucket && bucket > 0);
-        return (isPowerSaver && !hybridEnabled)
-                || plugged
-                || (standardWouldDismiss && (!mEnhancedEstimates.isHybridNotificationEnabled()
-                        || hybridWouldDismiss));
-    }
-
-    private boolean isEnhancedTrigger(boolean plugged, long timeRemaining, boolean isPowerSaver,
-            int batteryStatus) {
-        if (plugged || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
-            return false;
-        }
-        int warnLevel = mLowBatteryReminderLevels[0];
-        int critLevel = mLowBatteryReminderLevels[1];
-
-        // Only show the low warning once per charge cycle & no battery saver
-        final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !isPowerSaver
-                && (timeRemaining < mEnhancedEstimates.getLowWarningThreshold()
-                || mBatteryLevel <= warnLevel);
-
-        // Only show the severe warning once per charge cycle
-        final boolean canShowSevereWarning = !mSevereWarningShownThisChargeCycle
-                && (timeRemaining < mEnhancedEstimates.getSevereWarningThreshold()
-                || mBatteryLevel <= critLevel);
-
-        final boolean canShow = canShowWarning || canShowSevereWarning;
-        if (DEBUG) {
-            Slog.d(TAG, "Enhanced trigger is: " + canShow + "\nwith values: "
-                    + " mLowWarningShownThisChargeCycle: " + mLowWarningShownThisChargeCycle
-                    + " mSevereWarningShownThisChargeCycle: " + mSevereWarningShownThisChargeCycle
-                    + " mEnhancedEstimates.timeremaining: " + timeRemaining
-                    + " mBatteryLevel: " + mBatteryLevel
-                    + " canShowWarning: " + canShowWarning
-                    + " canShowSevereWarning: " + canShowSevereWarning
-                    + " plugged: " + plugged
-                    + " batteryStatus: " + batteryStatus
-                    + " isPowerSaver: " + isPowerSaver);
-        }
-        return canShowWarning || canShowSevereWarning;
+    boolean shouldDismissLowBatteryWarning(
+            BatteryStateSnapshot currentSnapshot,
+            BatteryStateSnapshot lastSnapshot) {
+        return currentSnapshot.isPowerSaver()
+                || currentSnapshot.getPlugged()
+                || (currentSnapshot.getBucket() > lastSnapshot.getBucket()
+                        && currentSnapshot.getBucket() > 0);
     }
 
     private void initTemperature() {
@@ -453,13 +520,21 @@
         mWarnings.dump(pw);
     }
 
+    /**
+     * The interface to allow PowerUI to communicate with whatever implementation of WarningsUI
+     * is being used by the system.
+     */
     public interface WarningsUI {
+
+        /**
+         * Updates battery and screen info for determining whether to trigger battery warnings or
+         * not.
+         * @param batteryLevel The current battery level
+         * @param bucket The current battery bucket
+         * @param screenOffTime How long the screen has been off in millis
+         */
         void update(int batteryLevel, int bucket, long screenOffTime);
 
-        void updateEstimate(Estimate estimate);
-
-        void updateThresholds(long lowThreshold, long severeThreshold);
-
         void dismissLowBatteryWarning();
 
         void showLowBatteryWarning(boolean playSound);
@@ -486,6 +561,12 @@
         void dump(PrintWriter pw);
 
         void userSwitched();
+
+        /**
+         * Updates the snapshot of battery state used for evaluating battery warnings
+         * @param snapshot object containing relevant values for making battery warning decisions.
+         */
+        void updateSnapshot(BatteryStateSnapshot snapshot);
     }
 
     // Thermal event received from thermal service manager subsystem
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 625eacd..1c0974a 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -61,7 +61,8 @@
 
     @VisibleForTesting
     internal var privacyList = emptyList<PrivacyItem>()
-        get() = field.toList() // Provides a shallow copy of the list
+        @Synchronized get() = field.toList() // Returns a shallow copy of the list
+        @Synchronized set
 
     private val userManager = context.getSystemService(UserManager::class.java)
     private var currentUserIds = emptyList<Int>()
@@ -71,7 +72,8 @@
     private val callbacks = mutableListOf<WeakReference<Callback>>()
 
     private val notifyChanges = Runnable {
-        callbacks.forEach { it.get()?.privacyChanged(privacyList) }
+        val list = privacyList
+        callbacks.forEach { it.get()?.privacyChanged(list) }
     }
 
     private val updateListAndNotifyChanges = Runnable {
@@ -157,8 +159,10 @@
     }
 
     private fun updatePrivacyList() {
-        privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
+
+        val list = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
                 .mapNotNull { toPrivacyItem(it) }.distinct()
+        privacyList = list
     }
 
     private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 6a8c19a..08cf606 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -15,7 +15,6 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
@@ -31,15 +30,12 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.media.AudioManager;
-import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.AlarmClock;
-import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
@@ -75,7 +71,6 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
 import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.DateView;
 import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -107,7 +102,6 @@
     public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
 
     private final Handler mHandler = new Handler();
-    private final BatteryController mBatteryController;
     private final NextAlarmController mAlarmController;
     private final ZenModeController mZenController;
     private final StatusBarIconController mStatusBarIconController;
@@ -162,9 +156,6 @@
     };
     private boolean mHasTopCutout = false;
 
-    private final PercentSettingObserver mPercentSettingObserver =
-            new PercentSettingObserver(new Handler(mContext.getMainLooper()));
-
     /**
      * Runnable for automatically fading out the long press tooltip (as if it were animating away).
      */
@@ -181,12 +172,11 @@
     @Inject
     public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
             NextAlarmController nextAlarmController, ZenModeController zenModeController,
-            BatteryController batteryController, StatusBarIconController statusBarIconController,
+            StatusBarIconController statusBarIconController,
             ActivityStarter activityStarter, PrivacyItemController privacyItemController) {
         super(context, attrs);
         mAlarmController = nextAlarmController;
         mZenController = zenModeController;
-        mBatteryController = batteryController;
         mStatusBarIconController = statusBarIconController;
         mActivityStarter = activityStarter;
         mPrivacyItemController = privacyItemController;
@@ -241,7 +231,9 @@
         mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
         // Don't need to worry about tuner settings for this icon
         mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
-        updateShowPercent();
+        // QS will always show the estimate, and BatteryMeterView handles the case where
+        // it's unavailable or charging
+        mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
     }
 
     private List<String> getIgnoredIconSlots() {
@@ -480,9 +472,6 @@
         super.onAttachedToWindow();
         mStatusBarIconController.addIconGroup(mIconManager);
         requestApplyInsets();
-        mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
-                ActivityManager.getCurrentUser());
     }
 
     @Override
@@ -521,7 +510,6 @@
     public void onDetachedFromWindow() {
         setListening(false);
         mStatusBarIconController.removeIconGroup(mIconManager);
-        mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
         super.onDetachedFromWindow();
     }
 
@@ -743,25 +731,4 @@
             lp.rightMargin = sideMargins;
         }
     }
-
-    private void updateShowPercent() {
-        final boolean systemSetting = 0 != Settings.System
-                .getIntForUser(getContext().getContentResolver(),
-                        SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
-
-        mBatteryRemainingIcon.setPercentShowMode(systemSetting
-                ? BatteryMeterView.MODE_ESTIMATE : BatteryMeterView.MODE_ON);
-    }
-
-    private final class PercentSettingObserver extends ContentObserver {
-        PercentSettingObserver(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            super.onChange(selfChange, uri);
-            updateShowPercent();
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 4dcacd4..7006249 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -27,6 +27,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -166,7 +167,8 @@
                 icon.mutate();
                 icon.setTint(mContext.getColor(android.R.color.white));
                 CharSequence label = info.serviceInfo.loadLabel(pm);
-                addTile(spec, icon, label != null ? label.toString() : "null", appLabel);
+                createStateAndAddTile(spec, icon, label != null ? label.toString() : "null",
+                        appLabel);
             }
 
             notifyTilesChanged(true);
@@ -207,9 +209,10 @@
         mSpecs.add(spec);
     }
 
-    private void addTile(
+    private void createStateAndAddTile(
             String spec, Drawable drawable, CharSequence label, CharSequence appLabel) {
         QSTile.State state = new QSTile.State();
+        state.state = Tile.STATE_INACTIVE;
         state.label = label;
         state.contentDescription = label;
         state.icon = new DrawableIcon(drawable);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index b794888..4da8ca2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.recents;
 
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
@@ -629,7 +629,7 @@
 
     private void updateEnabledState() {
         mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
-                MATCH_DIRECT_BOOT_UNAWARE,
+                MATCH_SYSTEM_ONLY,
                 ActivityManagerWrapper.getInstance().getCurrentUserId()) != null;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 0150852..295abcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -277,9 +277,13 @@
         default void hideBiometricDialog() { }
 
         /**
-        * @see IStatusBar#onDisplayReady(int)
-        */
+         * @see IStatusBar#onDisplayReady(int)
+         */
         default void onDisplayReady(int displayId) { }
+        /**
+         * @see DisplayManager.DisplayListener#onDisplayRemoved(int)
+         */
+        default void onDisplayRemoved(int displayId) { }
     }
 
     @VisibleForTesting
@@ -297,6 +301,11 @@
         synchronized (mLock) {
             mDisplayDisabled.remove(displayId);
         }
+        // This callback is registered with {@link #mHandler} that already posts to run on main
+        // thread, so it is safe to dispatch directly.
+        for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+            mCallbacks.get(i).onDisplayRemoved(displayId);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index 52b8cc2..b7ae4ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -51,8 +51,15 @@
         val renderScript = RenderScript.create(context)
         val rect = Rect(0, 0, artwork.width, artwork.height)
         MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
-        val inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
+        var inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
                 true /* filter */)
+        // Render script blurs only support ARGB_8888, we need a conversion if we got a
+        // different bitmap config.
+        if (inBitmap.config != Bitmap.Config.ARGB_8888) {
+            val oldIn = inBitmap
+            inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
+            oldIn.recycle()
+        }
         val input = Allocation.createFromBitmap(renderScript, inBitmap,
                 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
         val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 9f382ea..14dc272 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -23,7 +23,6 @@
 
 import android.content.Context;
 import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
@@ -50,7 +49,7 @@
 
 /** A controller to handle navigation bars. */
 @Singleton
-public class NavigationBarController implements DisplayListener, Callbacks {
+public class NavigationBarController implements Callbacks {
 
     private static final String TAG = NavigationBarController.class.getName();
 
@@ -66,22 +65,15 @@
         mContext = context;
         mHandler = handler;
         mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-        mDisplayManager.registerDisplayListener(this, mHandler);
         getComponent(mContext, CommandQueue.class).addCallback(this);
     }
 
     @Override
-    public void onDisplayAdded(int displayId) { }
-
-    @Override
     public void onDisplayRemoved(int displayId) {
         removeNavigationBar(displayId);
     }
 
     @Override
-    public void onDisplayChanged(int displayId) { }
-
-    @Override
     public void onDisplayReady(int displayId) {
         Display display = mDisplayManager.getDisplay(displayId);
         createNavigationBar(display);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index ad5aa57..eb386dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -18,15 +18,19 @@
 
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.text.format.DateFormat;
 import android.util.FloatProperty;
 import android.view.animation.Interpolator;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.policy.CallbackController;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Comparator;
 
@@ -38,8 +42,10 @@
  */
 @Singleton
 public class StatusBarStateControllerImpl implements SysuiStatusBarStateController,
-        CallbackController<StateListener> {
+        CallbackController<StateListener>, Dumpable {
     private static final String TAG = "SbStateController";
+    // Must be a power of 2
+    private static final int HISTORY_SIZE = 32;
 
     private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
     private static final int MIN_STATE = StatusBarState.SHADE;
@@ -66,6 +72,10 @@
     private boolean mLeaveOpenOnKeyguardHide;
     private boolean mKeyguardRequested;
 
+    // Record the HISTORY_SIZE most recent states
+    private int mHistoryIndex = 0;
+    private HistoricalState[] mHistoricalRecords = new HistoricalState[HISTORY_SIZE];
+
     /**
      * If the device is currently dozing or not.
      */
@@ -93,6 +103,9 @@
 
     @Inject
     public StatusBarStateControllerImpl() {
+        for (int i = 0; i < HISTORY_SIZE; i++) {
+            mHistoricalRecords[i] = new HistoricalState();
+        }
     }
 
     @Override
@@ -108,6 +121,10 @@
         if (state == mState) {
             return false;
         }
+
+        // Record the to-be mState and mLastState
+        recordHistoricalState(state, mState);
+
         synchronized (mListeners) {
             for (RankedListener rl : new ArrayList<>(mListeners)) {
                 rl.mListener.onStatePreChange(mState, state);
@@ -281,4 +298,58 @@
     public static String describe(int state) {
         return StatusBarState.toShortString(state);
     }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("StatusBarStateController: ");
+        pw.println(" mState=" + mState + " (" + describe(mState) + ")");
+        pw.println(" mLastState=" + mLastState + " (" + describe(mLastState) + ")");
+        pw.println(" mLeaveOpenOnKeyguardHide=" + mLeaveOpenOnKeyguardHide);
+        pw.println(" mKeyguardRequested=" + mKeyguardRequested);
+        pw.println(" mIsDozing=" + mIsDozing);
+        pw.println(" Historical states:");
+        // Ignore records without a timestamp
+        int size = 0;
+        for (int i = 0; i < HISTORY_SIZE; i++) {
+            if (mHistoricalRecords[i].mTimestamp != 0) size++;
+        }
+        for (int i = mHistoryIndex + HISTORY_SIZE;
+                i >= mHistoryIndex + HISTORY_SIZE - size + 1; i--) {
+            pw.println("  (" + (mHistoryIndex + HISTORY_SIZE - i + 1) + ")"
+                    + mHistoricalRecords[i & (HISTORY_SIZE - 1)]);
+        }
+    }
+
+    private void recordHistoricalState(int currentState, int lastState) {
+        mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE;
+        HistoricalState state = mHistoricalRecords[mHistoryIndex];
+        state.mState = currentState;
+        state.mLastState = lastState;
+        state.mTimestamp = System.currentTimeMillis();
+    }
+
+    /**
+     * For keeping track of our previous state to help with debugging
+     */
+    private static class HistoricalState {
+        int mState;
+        int mLastState;
+        long mTimestamp;
+
+        @Override
+        public String toString() {
+            if (mTimestamp != 0) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("state=").append(mState)
+                        .append(" (").append(describe(mState)).append(")");
+                sb.append("lastState=").append(mLastState).append(" (").append(describe(mLastState))
+                        .append(")");
+                sb.append("timestamp=")
+                        .append(DateFormat.format("MM-dd HH:mm:ss", mTimestamp));
+
+                return sb.toString();
+            }
+            return "Empty " + getClass().getSimpleName();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 767e14c..c769daa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -334,7 +334,6 @@
     private boolean mUseIncreasedHeadsUpHeight;
     private float mTranslationWhenRemoved;
     private boolean mWasChildInGroupWhenRemoved;
-    private int mNotificationColorAmbient;
     private NotificationInlineImageResolver mImageResolver;
     private NotificationMediaManager mMediaManager;
 
@@ -1284,18 +1283,12 @@
         mNotificationColor = ContrastColorUtil.resolveContrastColor(mContext,
                 getStatusBarNotification().getNotification().color,
                 getBackgroundColorWithoutTint(), nightMode);
-        mNotificationColorAmbient = ContrastColorUtil.resolveAmbientColor(mContext,
-                getStatusBarNotification().getNotification().color);
     }
 
     public HybridNotificationView getSingleLineView() {
         return mPrivateLayout.getSingleLineView();
     }
 
-    public HybridNotificationView getAmbientSingleLineView() {
-        return getShowingLayout().getAmbientSingleLineChild();
-    }
-
     public boolean isOnKeyguard() {
         return mOnKeyguard;
     }
@@ -1628,10 +1621,6 @@
         return mNotificationInflater;
     }
 
-    public int getNotificationColorAmbient() {
-        return mNotificationColorAmbient;
-    }
-
     public interface ExpansionLogger {
         void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -2316,7 +2305,7 @@
             return mPrivateLayout.getMinHeight();
         } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
             return getMinHeight();
-        } else if (mIsSummaryWithChildren && (!mOnKeyguard || mOnAmbient)) {
+        } else if (mIsSummaryWithChildren && !mOnKeyguard) {
             return mChildrenContainer.getIntrinsicHeight();
         } else if (isHeadsUpAllowed() && (mIsHeadsUp || mHeadsupDisappearRunning)) {
             if (isPinned() || mHeadsupDisappearRunning) {
@@ -3018,9 +3007,6 @@
     public void setOnAmbient(boolean onAmbient) {
         if (onAmbient != mOnAmbient) {
             mOnAmbient = onAmbient;
-            if (mChildrenContainer != null) {
-                mChildrenContainer.notifyDozingStateChanged();
-            }
             notifyHeightChanged(false /* needsAnimation */);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
index 90ff4a7..fe81957 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java
@@ -36,7 +36,6 @@
 public class HybridGroupManager {
 
     private final Context mContext;
-    private final NotificationDozeHelper mDozer;
     private final ViewGroup mParent;
 
     private float mOverflowNumberSize;
@@ -47,7 +46,6 @@
     public HybridGroupManager(Context ctx, ViewGroup parent) {
         mContext = ctx;
         mParent = parent;
-        mDozer = new NotificationDozeHelper();
         initDimens();
     }
 
@@ -94,12 +92,6 @@
                 R.style.HybridNotification);
     }
 
-    public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView,
-            Notification notification) {
-        return bindFromNotificationWithStyle(reusableView, notification,
-                R.style.HybridNotification);
-    }
-
     private HybridNotificationView bindFromNotificationWithStyle(
             HybridNotificationView reusableView, Notification notification, int style) {
         if (reusableView == null) {
@@ -147,15 +139,4 @@
         updateOverFlowNumberColor(reusableView);
         return reusableView;
     }
-
-    public TextView bindOverflowNumberAmbient(TextView titleView, Notification notification,
-            int number) {
-        String text = mContext.getResources().getString(
-                R.string.notification_group_overflow_indicator_ambient,
-                resolveTitle(notification), number);
-        if (!text.equals(titleView.getText())) {
-            titleView.setText(text);
-        }
-        return titleView;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 3cc2e83..7850035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -72,7 +72,6 @@
     public static final int VISIBLE_TYPE_HEADSUP = 2;
     private static final int VISIBLE_TYPE_SINGLELINE = 3;
     public static final int VISIBLE_TYPE_AMBIENT = 4;
-    private static final int VISIBLE_TYPE_AMBIENT_SINGLELINE = 5;
     public static final int UNDEFINED = -1;
 
     private final Rect mClipBounds = new Rect();
@@ -84,7 +83,6 @@
     private View mHeadsUpChild;
     private HybridNotificationView mSingleLineView;
     private View mAmbientChild;
-    private HybridNotificationView mAmbientSingleLineChild;
 
     private RemoteInputView mExpandedRemoteInput;
     private RemoteInputView mHeadsUpRemoteInput;
@@ -301,27 +299,6 @@
                             : MeasureSpec.AT_MOST));
             maxChildHeight = Math.max(maxChildHeight, mAmbientChild.getMeasuredHeight());
         }
-        if (mAmbientSingleLineChild != null) {
-            int size = mNotificationAmbientHeight;
-            ViewGroup.LayoutParams layoutParams = mAmbientSingleLineChild.getLayoutParams();
-            boolean useExactly = false;
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(size, layoutParams.height);
-                useExactly = true;
-            }
-            int ambientSingleLineWidthSpec = widthMeasureSpec;
-            if (mSingleLineWidthIndention != 0
-                    && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
-                ambientSingleLineWidthSpec = MeasureSpec.makeMeasureSpec(
-                        width - mSingleLineWidthIndention + mAmbientSingleLineChild.getPaddingEnd(),
-                        MeasureSpec.EXACTLY);
-            }
-            mAmbientSingleLineChild.measure(ambientSingleLineWidthSpec,
-                    MeasureSpec.makeMeasureSpec(size, useExactly ? MeasureSpec.EXACTLY
-                            : MeasureSpec.AT_MOST));
-            maxChildHeight = Math.max(maxChildHeight, mAmbientSingleLineChild.getMeasuredHeight());
-        }
         int ownHeight = Math.min(maxChildHeight, maxSize);
         setMeasuredDimension(width, ownHeight);
     }
@@ -351,22 +328,10 @@
             if (mExpandedChild != null
                     && mExpandedWrapper.getNotificationHeader() != null) {
                 NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
-                int expandedSize = expandedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                int collapsedSize = contractedHeader.getMeasuredWidth()
-                        - expandedHeader.getPaddingEnd();
-                if (expandedSize != collapsedSize) {
-                    int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
-                    contractedHeader.setPadding(
-                            contractedHeader.isLayoutRtl()
-                                    ? paddingEnd
-                                    : contractedHeader.getPaddingLeft(),
-                            contractedHeader.getPaddingTop(),
-                            contractedHeader.isLayoutRtl()
-                                    ? contractedHeader.getPaddingLeft()
-                                    : paddingEnd,
-                            contractedHeader.getPaddingBottom());
-                    contractedHeader.setShowWorkBadgeAtEnd(true);
+
+                int headerTextMargin = expandedHeader.getHeaderTextMarginEnd();
+                if (headerTextMargin != contractedHeader.getHeaderTextMarginEnd()) {
+                    contractedHeader.setHeaderTextMarginEnd(headerTextMargin);
                     return true;
                 }
             } else {
@@ -432,10 +397,6 @@
         return mAmbientChild;
     }
 
-    public HybridNotificationView getAmbientSingleLineChild() {
-        return mAmbientSingleLineChild;
-    }
-
     /**
      * Sets the contracted view. Child may be null to remove the content view.
      *
@@ -693,10 +654,7 @@
         int hint;
         if (mAmbientChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_AMBIENT)) {
             hint = mAmbientChild.getHeight();
-        } else if (mAmbientSingleLineChild != null && isVisibleOrTransitioning(
-                VISIBLE_TYPE_AMBIENT_SINGLELINE)) {
-            hint = mAmbientSingleLineChild.getHeight();
-        } else if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
+        }  else if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
             hint = getViewHeight(VISIBLE_TYPE_HEADSUP);
         } else if (mExpandedChild != null) {
             hint = getViewHeight(VISIBLE_TYPE_EXPANDED);
@@ -833,7 +791,7 @@
     }
 
     public View getShowingAmbientView() {
-        View v = mIsChildInGroup ? mAmbientSingleLineChild : mAmbientChild;
+        View v = mIsChildInGroup ? mSingleLineView : mAmbientChild;
         if (v != null) {
             return v;
         } else {
@@ -923,8 +881,6 @@
         forceUpdateVisibility(VISIBLE_TYPE_HEADSUP, mHeadsUpChild, mHeadsUpWrapper);
         forceUpdateVisibility(VISIBLE_TYPE_SINGLELINE, mSingleLineView, mSingleLineView);
         forceUpdateVisibility(VISIBLE_TYPE_AMBIENT, mAmbientChild, mAmbientWrapper);
-        forceUpdateVisibility(VISIBLE_TYPE_AMBIENT_SINGLELINE, mAmbientSingleLineChild,
-                mAmbientSingleLineChild);
         fireExpandedVisibleListenerIfVisible();
         // forceUpdateVisibilities cancels outstanding animations without updating the
         // mAnimationStartVisibleType. Do so here instead.
@@ -1002,8 +958,6 @@
                 mSingleLineView, mSingleLineView);
         updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT,
                 mAmbientChild, mAmbientWrapper);
-        updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
-                mAmbientSingleLineChild, mAmbientSingleLineChild);
         fireExpandedVisibleListenerIfVisible();
         // updateViewVisibilities cancels outstanding animations without updating the
         // mAnimationStartVisibleType. Do so here instead.
@@ -1066,8 +1020,6 @@
                 return mSingleLineView;
             case VISIBLE_TYPE_AMBIENT:
                 return mAmbientWrapper;
-            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
-                return mAmbientSingleLineChild;
             default:
                 return mContractedWrapper;
         }
@@ -1087,8 +1039,6 @@
                 return mSingleLineView;
             case VISIBLE_TYPE_AMBIENT:
                 return mAmbientChild;
-            case VISIBLE_TYPE_AMBIENT_SINGLELINE:
-                return mAmbientSingleLineChild;
             default:
                 return mContractedChild;
         }
@@ -1145,8 +1095,7 @@
         }
         boolean onAmbient = mContainingNotification.isOnAmbient();
         if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
-            return onAmbient ? VISIBLE_TYPE_AMBIENT_SINGLELINE
-                    : VISIBLE_TYPE_SINGLELINE;
+            return VISIBLE_TYPE_SINGLELINE;
         }
 
         if ((mIsHeadsUp || mHeadsUpAnimatingAway) && mHeadsUpChild != null
@@ -1259,7 +1208,6 @@
 
     private void updateAllSingleLineViews() {
         updateSingleLineView();
-        updateAmbientSingleLineView();
     }
 
     private void updateSingleLineView() {
@@ -1277,21 +1225,6 @@
         }
     }
 
-    private void updateAmbientSingleLineView() {
-        if (mIsChildInGroup) {
-            boolean isNewView = mAmbientSingleLineChild == null;
-            mAmbientSingleLineChild = mHybridGroupManager.bindAmbientFromNotification(
-                    mAmbientSingleLineChild, mStatusBarNotification.getNotification());
-            if (isNewView) {
-                updateViewVisibility(mVisibleType, VISIBLE_TYPE_AMBIENT_SINGLELINE,
-                        mAmbientSingleLineChild, mAmbientSingleLineChild);
-            }
-        } else if (mAmbientSingleLineChild != null) {
-            removeView(mAmbientSingleLineChild);
-            mAmbientSingleLineChild = null;
-        }
-    }
-
     private void applyMediaTransfer(final NotificationEntry entry) {
         View bigContentView = mExpandedChild;
         if (bigContentView == null || !entry.isMediaNotification()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 8ffada4..6632ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -55,8 +55,6 @@
     static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
     @VisibleForTesting
     static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
-    @VisibleForTesting
-    static final int NUMBER_OF_CHILDREN_WHEN_AMBIENT = 1;
     private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
         private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
 
@@ -95,8 +93,6 @@
     private NotificationViewWrapper mNotificationHeaderWrapper;
     private NotificationHeaderView mNotificationHeaderLowPriority;
     private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
-    private ViewGroup mNotificationHeaderAmbient;
-    private NotificationViewWrapper mNotificationHeaderWrapperAmbient;
     private NotificationHeaderUtil mHeaderUtil;
     private ViewState mHeaderViewState;
     private int mClipBottomAmount;
@@ -180,11 +176,6 @@
                     mNotificationHeaderLowPriority.getMeasuredWidth(),
                     mNotificationHeaderLowPriority.getMeasuredHeight());
         }
-        if (mNotificationHeaderAmbient != null) {
-            mNotificationHeaderAmbient.layout(0, 0,
-                    mNotificationHeaderAmbient.getMeasuredWidth(),
-                    mNotificationHeaderAmbient.getMeasuredHeight());
-        }
     }
 
     @Override
@@ -212,8 +203,7 @@
             // We need to measure all children even the GONE ones, such that the heights are
             // calculated correctly as they are used to calculate how many we can fit on the screen.
             boolean isOverflow = i == overflowIndex;
-            child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null &&
-                    !mContainingNotification.isOnAmbient()
+            child.setSingleLineWidthIndention(isOverflow && mOverflowNumber != null
                     ? mOverflowNumber.getMeasuredWidth() : 0);
             child.measure(widthMeasureSpec, newHeightSpec);
             // layout the divider
@@ -236,10 +226,6 @@
             headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
             mNotificationHeaderLowPriority.measure(widthMeasureSpec, headerHeightSpec);
         }
-        if (mNotificationHeaderAmbient != null) {
-            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
-            mNotificationHeaderAmbient.measure(widthMeasureSpec, headerHeightSpec);
-        }
 
         setMeasuredDimension(width, height);
     }
@@ -332,33 +318,10 @@
         }
         mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
         recreateLowPriorityHeader(builder);
-        recreateAmbientHeader(builder);
         updateHeaderVisibility(false /* animate */);
         updateChildrenHeaderAppearance();
     }
 
-    private void recreateAmbientHeader(Notification.Builder builder) {
-        RemoteViews header;
-        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
-        if (builder == null) {
-            builder = Notification.Builder.recoverBuilder(getContext(),
-                    notification.getNotification());
-        }
-        header = builder.makeNotificationHeader();
-        if (mNotificationHeaderAmbient == null) {
-            mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this);
-            mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(),
-                    mNotificationHeaderAmbient, mContainingNotification);
-            mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
-            addView(mNotificationHeaderAmbient, 0);
-            invalidate();
-        } else {
-            header.reapply(getContext(), mNotificationHeaderAmbient);
-        }
-        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, calculateDesiredHeader());
-        mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
-    }
-
     /**
      * Recreate the low-priority header.
      *
@@ -406,17 +369,6 @@
         if (childCount > maxAllowedVisibleChildren) {
             int number = childCount - maxAllowedVisibleChildren;
             mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number);
-            if (mContainingNotification.isOnAmbient()) {
-                ExpandableNotificationRow overflowView = mChildren.get(0);
-                HybridNotificationView ambientSingleLineView = overflowView == null ? null
-                        : overflowView.getAmbientSingleLineView();
-                if (ambientSingleLineView != null) {
-                    mHybridGroupManager.bindOverflowNumberAmbient(
-                            ambientSingleLineView.getTitleView(),
-                            mContainingNotification.getStatusBarNotification().getNotification(),
-                            number);
-                }
-            }
             if (mGroupOverFlowState == null) {
                 mGroupOverFlowState = new ViewState();
                 mNeverAppliedGroupState = true;
@@ -522,7 +474,7 @@
         if (mUserLocked) {
             expandFactor = getGroupExpandFraction();
         }
-        boolean childrenExpanded = mChildrenExpanded || mContainingNotification.isOnAmbient();
+        boolean childrenExpanded = mChildrenExpanded;
         for (int i = 0; i < childCount; i++) {
             if (visibleChildren >= maxAllowedVisibleChildren) {
                 break;
@@ -563,7 +515,7 @@
     /**
      * Update the state of all its children based on a linear layout algorithm.
      * @param parentState the state of the parent
-     * @param ambientState
+     * @param ambientState the ambient state containing ambient information
      */
     public void updateState(ExpandableViewState parentState, AmbientState ambientState) {
         int childCount = mChildren.size();
@@ -639,9 +591,7 @@
                     getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1);
             mGroupOverFlowState.copyFrom(overflowView.getViewState());
 
-            if (mContainingNotification.isOnAmbient()) {
-                mGroupOverFlowState.alpha = 0.0f;
-            } else if (!mChildrenExpanded) {
+            if (!mChildrenExpanded) {
                 HybridNotificationView alignView = overflowView.getSingleLineView();
                 if (alignView != null) {
                     View mirrorView = alignView.getTextView();
@@ -708,9 +658,6 @@
 
     @VisibleForTesting
     int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
-        if (mContainingNotification.isOnAmbient()) {
-            return NUMBER_OF_CHILDREN_WHEN_AMBIENT;
-        }
         if (!likeCollapsed && (mChildrenExpanded || mContainingNotification.isUserLocked())
                 && !showingAsLowPriority()) {
             return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
@@ -900,11 +847,6 @@
         return mCurrentHeader;
     }
 
-    public void notifyDozingStateChanged() {
-        updateHeaderVisibility(false);
-        updateGroupOverflow();
-    }
-
     private void updateHeaderVisibility(boolean animate) {
         ViewGroup desiredHeader;
         ViewGroup currentHeader = mCurrentHeader;
@@ -913,10 +855,6 @@
         if (currentHeader == desiredHeader) {
             return;
         }
-        if (desiredHeader == mNotificationHeaderAmbient
-                || currentHeader == mNotificationHeaderAmbient) {
-            animate = false;
-        }
 
         if (animate) {
             if (desiredHeader != null && currentHeader != null) {
@@ -948,7 +886,6 @@
         }
 
         resetHeaderVisibilityIfNeeded(mNotificationHeader, desiredHeader);
-        resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, desiredHeader);
         resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, desiredHeader);
 
         mCurrentHeader = desiredHeader;
@@ -970,9 +907,7 @@
 
     private ViewGroup calculateDesiredHeader() {
         ViewGroup desiredHeader;
-        if (mContainingNotification.isOnAmbient()) {
-            desiredHeader = mNotificationHeaderAmbient;
-        } else if (showingAsLowPriority()) {
+        if (showingAsLowPriority()) {
             desiredHeader = mNotificationHeaderLowPriority;
         } else {
             desiredHeader = mNotificationHeader;
@@ -1015,9 +950,6 @@
         if (visibleHeader == mNotificationHeader) {
             return mNotificationHeaderWrapper;
         }
-        if (visibleHeader == mNotificationHeaderAmbient) {
-            return mNotificationHeaderWrapperAmbient;
-        }
         return mNotificationHeaderWrapperLowPriority;
     }
 
@@ -1126,9 +1058,7 @@
     }
 
     public int getMinHeight() {
-        return getMinHeight(mContainingNotification.isOnAmbient()
-                ? NUMBER_OF_CHILDREN_WHEN_AMBIENT
-                : NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
+        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
     }
 
     public int getCollapsedHeight() {
@@ -1180,10 +1110,6 @@
             removeView(mNotificationHeaderLowPriority);
             mNotificationHeaderLowPriority = null;
         }
-        if (mNotificationHeaderAmbient != null) {
-            removeView(mNotificationHeaderAmbient);
-            mNotificationHeaderAmbient = null;
-        }
         recreateNotificationHeader(listener);
         initDimens();
         for (int i = 0; i < mDividers.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index b9425d4..2bbc53c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -75,6 +75,13 @@
         mDisplayId = context.getDisplayId();
     }
 
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        if (displayId == mDisplayId) {
+            mCommandQueue.removeCallback(this);
+        }
+    }
+
     void setStatusBar(StatusBar statusBar) {
         mStatusBar = statusBar;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 9be47f7..3fc60cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -990,6 +990,7 @@
         lp.setTitle("NavigationBar" + context.getDisplayId());
         lp.accessibilityTitle = context.getString(R.string.nav_bar);
         lp.windowAnimations = 0;
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
 
         View navigationBarView = LayoutInflater.from(context).inflate(
                 R.layout.navigation_bar_window, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a354885..142f398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -20,9 +20,6 @@
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
-
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -2956,6 +2953,9 @@
         if (mKeyguardStatusBar != null) {
             mKeyguardStatusBar.dump(fd, pw, args);
         }
+        if (mKeyguardStatusView != null) {
+            mKeyguardStatusView.dump(fd, pw, args);
+        }
     }
 
     public boolean hasActiveClearableNotifications() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 73ab527..3398fd34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -192,10 +192,6 @@
      */
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mStatusBar.isKeyguardShowing()) {
-            // Disallow any handling when the keyguard is showing
-            return false;
-        }
         return handleTouchEvent(event);
     }
 
@@ -205,11 +201,6 @@
      */
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mStatusBar.isKeyguardShowing()) {
-            // Disallow any handling when the keyguard is showing
-            return false;
-        }
-
         // The same down event was just sent on intercept and therefore can be ignored here
         final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
                 && mOverviewEventSender.getProxy() != null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7bbd3b5..8714a51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -114,6 +114,7 @@
     private final DozeParameters mDozeParameters;
     private final AlarmTimeout mTimeTicker;
     private final KeyguardVisibilityCallback mKeyguardVisibilityCallback;
+    private final Handler mHandler;
 
     private final SysuiColorExtractor mColorExtractor;
     private GradientColors mLockColors;
@@ -174,8 +175,9 @@
         mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
         mKeyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
         mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha);
+        mHandler = getHandler();
         mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
-                "hide_aod_wallpaper", new Handler());
+                "hide_aod_wallpaper", mHandler);
         mWakeLock = createWakeLock();
         // Scrim alpha is initially set to the value on the resource but might be changed
         // to make sure that text on top of it is legible.
@@ -253,8 +255,8 @@
             mScrimBehind.removeCallbacks(mPendingFrameCallback);
             mPendingFrameCallback = null;
         }
-        if (getHandler().hasCallbacks(mBlankingTransitionRunnable)) {
-            getHandler().removeCallbacks(mBlankingTransitionRunnable);
+        if (mHandler.hasCallbacks(mBlankingTransitionRunnable)) {
+            mHandler.removeCallbacks(mBlankingTransitionRunnable);
             mBlankingTransitionRunnable = null;
         }
 
@@ -768,7 +770,7 @@
             if (DEBUG) {
                 Log.d(TAG, "Fading out scrims with delay: " + delay);
             }
-            getHandler().postDelayed(mBlankingTransitionRunnable, delay);
+            mHandler.postDelayed(mBlankingTransitionRunnable, delay);
         };
         doOnTheNextFrame(mPendingFrameCallback);
     }
@@ -786,7 +788,7 @@
 
     @VisibleForTesting
     protected Handler getHandler() {
-        return Handler.getMain();
+        return new Handler();
     }
 
     public int getBackgroundColor() {
@@ -821,8 +823,7 @@
 
     @VisibleForTesting
     protected WakeLock createWakeLock() {
-         return new DelayedWakeLock(getHandler(),
-                WakeLock.createPartial(mContext, "Scrims"));
+        return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, "Scrims"));
     }
 
     @Override
@@ -853,12 +854,11 @@
      */
     public void onScreenTurnedOn() {
         mScreenOn = true;
-        final Handler handler = getHandler();
-        if (handler.hasCallbacks(mBlankingTransitionRunnable)) {
+        if (mHandler.hasCallbacks(mBlankingTransitionRunnable)) {
             if (DEBUG) {
                 Log.d(TAG, "Shorter blanking because screen turned on. All good.");
             }
-            handler.removeCallbacks(mBlankingTransitionRunnable);
+            mHandler.removeCallbacks(mBlankingTransitionRunnable);
             mBlankingTransitionRunnable.run();
         }
     }
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 d18b419..0ca4e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3208,7 +3208,9 @@
 
         boolean sleepingFromKeyguard =
                 mStatusBarKeyguardViewManager.isGoingToSleepVisibleNotOccluded();
-        boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup())
+        boolean wakeAndUnlock = mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+        boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
                 || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
 
         mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index ce69a48..8d71ab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -280,6 +280,15 @@
         }
     }
 
+    private void applyStatusBarColorSpaceAgnosticFlag(State state) {
+        if (!isExpanded(state)) {
+            mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
+        } else {
+            mLpChanged.privateFlags &=
+                    ~WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
+        }
+    }
+
     private void apply(State state) {
         applyKeyguardFlags(state);
         applyForceStatusBarVisibleFlag(state);
@@ -294,6 +303,7 @@
         applyBrightness(state);
         applyHasTopUi(state);
         applyNotTouchable(state);
+        applyStatusBarColorSpaceAgnosticFlag(state);
         if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
             mWindowManager.updateViewLayout(mStatusBarView, mLp);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 5e94152..111cdd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.annotation.Nullable;
+
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dumpable;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -78,6 +80,6 @@
          * The callback
          * @param estimate the estimate
          */
-        void onBatteryRemainingEstimateRetrieved(String estimate);
+        void onBatteryRemainingEstimateRetrieved(@Nullable String estimate);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index af3c96f..273fa55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -226,7 +226,7 @@
 
         String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
         return PowerUtil.getBatteryRemainingShortStringFormatted(
-                mContext, mEstimate.estimateMillis);
+                mContext, mEstimate.getEstimateMillis());
     }
 
     private void updateEstimateInBackground() {
@@ -237,10 +237,10 @@
 
         mFetchingEstimate = true;
         Dependency.get(Dependency.BG_HANDLER).post(() -> {
-            mEstimate = mEstimates.getEstimate();
+            // Only fetch the estimate if they are enabled
+            mEstimate = mEstimates.isHybridNotificationEnabled() ? mEstimates.getEstimate() : null;
             mLastEstimateTimestamp = System.currentTimeMillis();
             mFetchingEstimate = false;
-
             Dependency.get(Dependency.MAIN_HANDLER).post(this::notifyEstimateFetchCallbacks);
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index b561ac1..db2be0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -93,14 +93,28 @@
         return null;
     }
 
+    /**
+     * Adds {@code callback} to the controller. The controller will update the callback on state
+     * changes. It will immediately trigger the callback added to notify current state.
+     * @param callback
+     */
     @Override
     public void addCallback(Callback callback) {
         synchronized (mCallbacks) {
             if (callback == null || mCallbacks.contains(callback)) return;
             if (DEBUG) Log.d(TAG, "addCallback " + callback);
             mCallbacks.add(callback);
-
-            updateWifiStateListeners(!mCallbacks.isEmpty());
+            if (mWifiManager != null) {
+                if (mCallbacks.size() == 1) {
+                    mWifiManager.registerSoftApCallback(this, mMainHandler);
+                } else {
+                    // mWifiManager#registerSoftApCallback triggers a call to onNumClientsChanged
+                    // on the Main Handler. In order to always update the callback on added, we
+                    // make this call when adding callbacks after the first.
+                    mMainHandler.post(() ->
+                            callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices));
+                }
+            }
         }
     }
 
@@ -110,27 +124,9 @@
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         synchronized (mCallbacks) {
             mCallbacks.remove(callback);
-            updateWifiStateListeners(!mCallbacks.isEmpty());
-        }
-    }
-
-    /**
-     * Updates the wifi state receiver to either start or stop listening to get updates to the
-     * hotspot status. Additionally starts listening to wifi manager state to track the number of
-     * connected devices.
-     *
-     * @param shouldListen whether we should start listening to various wifi statuses
-     */
-    private void updateWifiStateListeners(boolean shouldListen) {
-        if (mWifiManager == null) {
-            return;
-        }
-        if (shouldListen) {
-            mWifiManager.registerSoftApCallback(
-                    this,
-                    mMainHandler);
-        } else {
-            mWifiManager.unregisterSoftApCallback(this);
+            if (mCallbacks.isEmpty() && mWifiManager != null) {
+                mWifiManager.unregisterSoftApCallback(this);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
index d8ea1f6..5b2e398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java
@@ -21,12 +21,18 @@
 import android.app.Notification;
 import android.app.RemoteInput;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.util.Log;
 import android.util.Pair;
 import android.widget.Button;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
@@ -191,14 +197,47 @@
             boolean useSmartActions = !ArrayUtils.isEmpty(entry.systemGeneratedSmartActions)
                     && notification.getAllowSystemGeneratedContextualActions();
             if (useSmartActions) {
+                List<Notification.Action> systemGeneratedActions =
+                        entry.systemGeneratedSmartActions;
+                // Filter actions if we're in kiosk-mode - we don't care about screen pinning mode,
+                // since notifications aren't shown there anyway.
+                ActivityManagerWrapper activityManagerWrapper =
+                        Dependency.get(ActivityManagerWrapper.class);
+                if (activityManagerWrapper.isLockTaskKioskModeActive()) {
+                    systemGeneratedActions = filterWhiteListedLockTaskApps(systemGeneratedActions);
+                }
                 smartActions = new SmartReplyView.SmartActions(
-                        entry.systemGeneratedSmartActions, true /* fromAssistant */);
+                        systemGeneratedActions, true /* fromAssistant */);
             }
         }
         return new SmartRepliesAndActions(smartReplies, smartActions);
     }
 
     /**
+     * Filter actions so that only actions pointing to whitelisted apps are allowed.
+     * This filtering is only meaningful when in lock-task mode.
+     */
+    private static List<Notification.Action> filterWhiteListedLockTaskApps(
+            List<Notification.Action> actions) {
+        PackageManagerWrapper packageManagerWrapper = Dependency.get(PackageManagerWrapper.class);
+        DevicePolicyManagerWrapper devicePolicyManagerWrapper =
+                Dependency.get(DevicePolicyManagerWrapper.class);
+        List<Notification.Action> filteredActions = new ArrayList<>();
+        for (Notification.Action action : actions) {
+            if (action.actionIntent == null) continue;
+            Intent intent = action.actionIntent.getIntent();
+            //  Only allow actions that are explicit (implicit intents are not handled in lock-task
+            //  mode), and link to whitelisted apps.
+            ResolveInfo resolveInfo = packageManagerWrapper.resolveActivity(intent, 0 /* flags */);
+            if (resolveInfo != null && devicePolicyManagerWrapper.isLockTaskPermitted(
+                    resolveInfo.activityInfo.packageName)) {
+                filteredActions.add(action);
+            }
+        }
+        return filteredActions;
+    }
+
+    /**
      * Returns whether the {@link Notification} represented by entry has a free-form remote input.
      * Such an input can be used e.g. to implement smart reply buttons - by passing the replies
      * through the remote input.
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java
index c6d6218..7edb5a5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Util.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java
@@ -16,52 +16,13 @@
 
 package com.android.systemui.volume;
 
-import android.content.Context;
 import android.media.AudioManager;
-import android.media.MediaMetadata;
-import android.media.VolumeProvider;
-import android.media.session.MediaController.PlaybackInfo;
-import android.media.session.PlaybackState;
-import android.telephony.TelephonyManager;
 import android.view.View;
-import android.widget.TextView;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Objects;
 
 /**
  * Static helpers for the volume dialog.
  */
-class Util {
-
-    // Note: currently not shown (only used in the text footer)
-    private static final SimpleDateFormat HMMAA = new SimpleDateFormat("h:mm aa", Locale.US);
-
-    private static int[] AUDIO_MANAGER_FLAGS = new int[] {
-        AudioManager.FLAG_SHOW_UI,
-        AudioManager.FLAG_VIBRATE,
-        AudioManager.FLAG_PLAY_SOUND,
-        AudioManager.FLAG_ALLOW_RINGER_MODES,
-        AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE,
-        AudioManager.FLAG_SHOW_VIBRATE_HINT,
-        AudioManager.FLAG_SHOW_SILENT_HINT,
-        AudioManager.FLAG_FROM_KEY,
-        AudioManager.FLAG_SHOW_UI_WARNINGS,
-    };
-
-    private static String[] AUDIO_MANAGER_FLAG_NAMES = new String[] {
-        "SHOW_UI",
-        "VIBRATE",
-        "PLAY_SOUND",
-        "ALLOW_RINGER_MODES",
-        "REMOVE_SOUND_AND_VIBRATE",
-        "SHOW_VIBRATE_HINT",
-        "SHOW_SILENT_HINT",
-        "FROM_KEY",
-        "SHOW_UI_WARNINGS",
-    };
+class Util extends com.android.settingslib.volume.Util {
 
     public static String logTag(Class<?> c) {
         final String tag = "vol." + c.getSimpleName();
@@ -70,106 +31,19 @@
 
     public static String ringerModeToString(int ringerMode) {
         switch (ringerMode) {
-            case AudioManager.RINGER_MODE_SILENT: return "RINGER_MODE_SILENT";
-            case AudioManager.RINGER_MODE_VIBRATE: return "RINGER_MODE_VIBRATE";
-            case AudioManager.RINGER_MODE_NORMAL: return "RINGER_MODE_NORMAL";
-            default: return "RINGER_MODE_UNKNOWN_" + ringerMode;
+            case AudioManager.RINGER_MODE_SILENT:
+                return "RINGER_MODE_SILENT";
+            case AudioManager.RINGER_MODE_VIBRATE:
+                return "RINGER_MODE_VIBRATE";
+            case AudioManager.RINGER_MODE_NORMAL:
+                return "RINGER_MODE_NORMAL";
+            default:
+                return "RINGER_MODE_UNKNOWN_" + ringerMode;
         }
     }
 
-    public static String mediaMetadataToString(MediaMetadata metadata) {
-        if (metadata == null) return null;
-        return metadata.getDescription().toString();
-    }
-
-    public static String playbackInfoToString(PlaybackInfo info) {
-        if (info == null) return null;
-        final String type = playbackInfoTypeToString(info.getPlaybackType());
-        final String vc = volumeProviderControlToString(info.getVolumeControl());
-        return String.format("PlaybackInfo[vol=%s,max=%s,type=%s,vc=%s],atts=%s",
-                info.getCurrentVolume(), info.getMaxVolume(), type, vc, info.getAudioAttributes());
-    }
-
-    public static String playbackInfoTypeToString(int type) {
-        switch (type) {
-            case PlaybackInfo.PLAYBACK_TYPE_LOCAL: return "LOCAL";
-            case PlaybackInfo.PLAYBACK_TYPE_REMOTE: return "REMOTE";
-            default: return "UNKNOWN_" + type;
-        }
-    }
-
-    public static String playbackStateStateToString(int state) {
-        switch (state) {
-            case PlaybackState.STATE_NONE: return "STATE_NONE";
-            case PlaybackState.STATE_STOPPED: return "STATE_STOPPED";
-            case PlaybackState.STATE_PAUSED: return "STATE_PAUSED";
-            case PlaybackState.STATE_PLAYING: return "STATE_PLAYING";
-            default: return "UNKNOWN_" + state;
-        }
-    }
-
-    public static String volumeProviderControlToString(int control) {
-        switch (control) {
-            case VolumeProvider.VOLUME_CONTROL_ABSOLUTE: return "VOLUME_CONTROL_ABSOLUTE";
-            case VolumeProvider.VOLUME_CONTROL_FIXED: return "VOLUME_CONTROL_FIXED";
-            case VolumeProvider.VOLUME_CONTROL_RELATIVE: return "VOLUME_CONTROL_RELATIVE";
-            default: return "VOLUME_CONTROL_UNKNOWN_" + control;
-        }
-    }
-
-    public static String playbackStateToString(PlaybackState playbackState) {
-        if (playbackState == null) return null;
-        return playbackStateStateToString(playbackState.getState()) + " " + playbackState;
-    }
-
-    public static String audioManagerFlagsToString(int value) {
-        return bitFieldToString(value, AUDIO_MANAGER_FLAGS, AUDIO_MANAGER_FLAG_NAMES);
-    }
-
-    private static String bitFieldToString(int value, int[] values, String[] names) {
-        if (value == 0) return "";
-        final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if ((value & values[i]) != 0) {
-                if (sb.length() > 0) sb.append(',');
-                sb.append(names[i]);
-            }
-            value &= ~values[i];
-        }
-        if (value != 0) {
-            if (sb.length() > 0) sb.append(',');
-            sb.append("UNKNOWN_").append(value);
-        }
-        return sb.toString();
-    }
-
-    public static String getShortTime(long millis) {
-        return HMMAA.format(new Date(millis));
-    }
-
-    private static CharSequence emptyToNull(CharSequence str) {
-        return str == null || str.length() == 0 ? null : str;
-    }
-
-    public static boolean setText(TextView tv, CharSequence text) {
-        if (Objects.equals(emptyToNull(tv.getText()), emptyToNull(text))) return false;
-        tv.setText(text);
-        return true;
-    }
-
     public static final void setVisOrGone(View v, boolean vis) {
         if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
         v.setVisibility(vis ? View.VISIBLE : View.GONE);
     }
-
-    public static final void setVisOrInvis(View v, boolean vis) {
-        if (v == null || (v.getVisibility() == View.VISIBLE) == vis) return;
-        v.setVisibility(vis ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    public static boolean isVoiceCapable(Context context) {
-        final TelephonyManager telephony =
-                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        return telephony != null && telephony.isVoiceCapable();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 32bc01c..4c16297 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -53,6 +53,7 @@
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.settingslib.volume.MediaSessions;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
new file mode 100644
index 0000000..587005e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
+import android.testing.AndroidTestingRunner;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SizeCompatModeActivityController.RestartActivityButton;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * runtest systemui -c com.android.systemui.SizeCompatModeActivityControllerTest
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class SizeCompatModeActivityControllerTest extends SysuiTestCase {
+    private static final int DISPLAY_ID = 0;
+
+    private SizeCompatModeActivityController mController;
+    private TaskStackChangeListener mTaskStackListener;
+    private @Mock ActivityManagerWrapper mMockAm;
+    private @Mock RestartActivityButton mMockButton;
+    private @Mock IBinder mMockActivityToken;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new SizeCompatModeActivityController(mMockAm) {
+            @Override
+            RestartActivityButton createRestartButton(Context context) {
+                return mMockButton;
+            };
+        };
+        mController.mContext = mContext;
+
+        ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
+                ArgumentCaptor.forClass(TaskStackChangeListener.class);
+        verify(mMockAm).registerTaskStackListener(listenerCaptor.capture());
+        mTaskStackListener = listenerCaptor.getValue();
+    }
+
+    @Test
+    public void testOnSizeCompatModeActivityChanged() {
+        // Verifies that the restart button is added with non-null component name.
+        mTaskStackListener.onSizeCompatModeActivityChanged(DISPLAY_ID, mMockActivityToken);
+        verify(mMockButton).show();
+        verify(mMockButton).updateLastTargetActivity(eq(mMockActivityToken));
+
+        // Verifies that the restart button is removed with null component name.
+        mTaskStackListener.onSizeCompatModeActivityChanged(DISPLAY_ID, null /* activityToken */);
+        verify(mMockButton).remove();
+    }
+
+    @Test
+    public void testChangeButtonVisibilityOnImeShowHide() {
+        mTaskStackListener.onSizeCompatModeActivityChanged(DISPLAY_ID, mMockActivityToken);
+
+        // Verifies that the restart button is hidden when IME is visible.
+        doReturn(View.VISIBLE).when(mMockButton).getVisibility();
+        mController.setImeWindowStatus(DISPLAY_ID, null /* token */, InputMethodService.IME_VISIBLE,
+                0 /* backDisposition */, false /* showImeSwitcher */);
+        verify(mMockButton).setVisibility(eq(View.GONE));
+
+        // Verifies that the restart button is visible when IME is hidden.
+        doReturn(View.GONE).when(mMockButton).getVisibility();
+        mController.setImeWindowStatus(DISPLAY_ID, null /* token */, 0 /* vis */,
+                0 /* backDisposition */, false /* showImeSwitcher */);
+        verify(mMockButton).setVisibility(eq(View.VISIBLE));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 943d927..cf25a9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -177,6 +177,7 @@
     }
 
     @Test
+    @Ignore("Occasionally flakes, ignoring pending investigation.")
     public void testChildRemoved() throws InterruptedException {
         assertEquals(0, mLayout.getTransientViewCount());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 5876ae1..58c9311 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -30,6 +30,7 @@
 
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.os.BatteryManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -57,6 +58,9 @@
         // Test Instance.
         mContext.addMockSystemService(NotificationManager.class, mMockNotificationManager);
         mPowerNotificationWarnings = new PowerNotificationWarnings(mContext);
+        BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1,
+                BatteryManager.BATTERY_HEALTH_GOOD, 5, 15);
+        mPowerNotificationWarnings.updateSnapshot(snapshot);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 0aed63d..f51e473 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -17,8 +17,7 @@
 import static android.provider.Settings.Global.SHOW_TEMPERATURE_WARNING;
 import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.anyObject;
@@ -29,7 +28,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.Intent;
 import android.os.BatteryManager;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
@@ -42,22 +40,20 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.testing.TestableResources;
 
-import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.power.PowerUI.WarningsUI;
 import com.android.systemui.statusbar.phone.StatusBar;
 
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.time.Duration;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
@@ -75,6 +71,7 @@
     private static final int OLD_BATTERY_LEVEL_NINE = 9;
     private static final int OLD_BATTERY_LEVEL_10 = 10;
     private static final long VERY_BELOW_SEVERE_HYBRID_THRESHOLD = TimeUnit.MINUTES.toMillis(15);
+    public static final int BATTERY_LEVEL_10 = 10;
     private WarningsUI mMockWarnings;
     private PowerUI mPowerUI;
     private EnhancedEstimates mEnhancedEstimates;
@@ -176,368 +173,333 @@
     }
 
     @Test
-    public void testShouldShowLowBatteryWarning_showHybridOnly_overrideThresholdHigh_returnsNoShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold())
-                .thenReturn(Duration.ofHours(1).toMillis());
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+    public void testMaybeShowHybridWarning() {
         mPowerUI.start();
 
-        // unplugged device that would not show the non-hybrid notification but would show the
-        // hybrid but the threshold has been overriden to be too low
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
+        // verify low warning shown this cycle noticed
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
+        BatteryStateSnapshot lastState = state.get();
+        state.mTimeRemainingMillis = Duration.ofHours(2).toMillis();
+        state.mBatteryLevel = 15;
+
+        mPowerUI.maybeShowHybridWarning(state.get(), lastState);
+
+        assertThat(mPowerUI.mLowWarningShownThisChargeCycle).isTrue();
+        assertThat(mPowerUI.mSevereWarningShownThisChargeCycle).isFalse();
+
+        // verify severe warning noticed this cycle
+        lastState = state.get();
+        state.mBatteryLevel = 1;
+        state.mTimeRemainingMillis = Duration.ofMinutes(10).toMillis();
+
+        mPowerUI.maybeShowHybridWarning(state.get(), lastState);
+
+        assertThat(mPowerUI.mLowWarningShownThisChargeCycle).isTrue();
+        assertThat(mPowerUI.mSevereWarningShownThisChargeCycle).isTrue();
+
+        // verify getting past threshold resets values
+        lastState = state.get();
+        state.mBatteryLevel = 100;
+        state.mTimeRemainingMillis = Duration.ofDays(1).toMillis();
+
+        mPowerUI.maybeShowHybridWarning(state.get(), lastState);
+
+        assertThat(mPowerUI.mLowWarningShownThisChargeCycle).isFalse();
+        assertThat(mPowerUI.mSevereWarningShownThisChargeCycle).isFalse();
     }
 
     @Test
-    public void testShouldShowLowBatteryWarning_showHybridOnly_overrideThresholdHigh_returnsShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold())
-                .thenReturn(Duration.ofHours(5).toMillis());
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+    public void testShouldShowHybridWarning_lowLevelWarning() {
         mPowerUI.start();
+        mPowerUI.mLowWarningShownThisChargeCycle = false;
+        mPowerUI.mSevereWarningShownThisChargeCycle = false;
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
 
-        // unplugged device that would not show the non-hybrid notification but would show the
-        // hybrid since the threshold has been overriden to be much higher
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertTrue(shouldShow);
+        // sanity check to make sure we can show for a valid config
+        state.mBatteryLevel = 10;
+        state.mTimeRemainingMillis = Duration.ofHours(2).toMillis();
+        boolean shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Shouldn't show if plugged in
+        state.mPlugged = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Shouldn't show if battery is unknown
+        state.mPlugged = false;
+        state.mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        state.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+        // Already shown both warnings
+        mPowerUI.mLowWarningShownThisChargeCycle = true;
+        mPowerUI.mSevereWarningShownThisChargeCycle = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Can show low warning
+        mPowerUI.mLowWarningShownThisChargeCycle = false;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Can't show if above the threshold for time & battery
+        state.mTimeRemainingMillis = Duration.ofHours(1000).toMillis();
+        state.mBatteryLevel = 100;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Battery under low percentage threshold but not time
+        state.mBatteryLevel = 10;
+        state.mLowLevelThreshold = 50;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Should also trigger if both level and time remaining under low threshold
+        state.mTimeRemainingMillis = Duration.ofHours(2).toMillis();
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // battery saver should block the low level warning though
+        state.mIsPowerSaver = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
     }
 
     @Test
-    public void testShouldShowLowBatteryWarning_showHybridOnly_returnsShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
+    public void testShouldShowHybridWarning_severeLevelWarning() {
         mPowerUI.start();
+        mPowerUI.mLowWarningShownThisChargeCycle = false;
+        mPowerUI.mSevereWarningShownThisChargeCycle = false;
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
 
-        // unplugged device that would not show the non-hybrid notification but would show the
-        // hybrid
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertTrue(shouldShow);
+        // sanity check to make sure we can show for a valid config
+        state.mBatteryLevel = 1;
+        state.mTimeRemainingMillis = Duration.ofMinutes(1).toMillis();
+        boolean shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Shouldn't show if plugged in
+        state.mPlugged = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Shouldn't show if battery is unknown
+        state.mPlugged = false;
+        state.mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        state.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+        // Already shown both warnings
+        mPowerUI.mLowWarningShownThisChargeCycle = true;
+        mPowerUI.mSevereWarningShownThisChargeCycle = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Can show severe warning
+        mPowerUI.mSevereWarningShownThisChargeCycle = false;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Can't show if above the threshold for time & battery
+        state.mTimeRemainingMillis = Duration.ofHours(1000).toMillis();
+        state.mBatteryLevel = 100;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isFalse();
+
+        // Battery under low percentage threshold but not time
+        state.mBatteryLevel = 1;
+        state.mSevereLevelThreshold = 5;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // Should also trigger if both level and time remaining under low threshold
+        state.mTimeRemainingMillis = Duration.ofHours(2).toMillis();
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
+
+        // battery saver should not block the severe level warning though
+        state.mIsPowerSaver = true;
+        shouldShow = mPowerUI.shouldShowHybridWarning(state.get());
+        assertThat(shouldShow).isTrue();
     }
 
     @Test
-    public void testShouldShowLowBatteryWarning_showHybrid_showStandard_returnsShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.mBatteryLevel = 10;
+    public void testShouldDismissHybridWarning() {
         mPowerUI.start();
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
 
-        // unplugged device that would show the non-hybrid notification and the hybrid
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertTrue(shouldShow);
+        // We should dismiss if the device is plugged in
+        state.mPlugged = true;
+        state.mTimeRemainingMillis = Duration.ofHours(1).toMillis();
+        state.mLowThresholdMillis = Duration.ofHours(2).toMillis();
+        boolean shouldDismiss = mPowerUI.shouldDismissHybridWarning(state.get());
+        assertThat(shouldDismiss).isTrue();
+
+        // If not plugged in and below the threshold we should not dismiss
+        state.mPlugged = false;
+        shouldDismiss = mPowerUI.shouldDismissHybridWarning(state.get());
+        assertThat(shouldDismiss).isFalse();
+
+        // If we go over the low warning threshold we should dismiss
+        state.mTimeRemainingMillis = Duration.ofHours(3).toMillis();
+        shouldDismiss = mPowerUI.shouldDismissHybridWarning(state.get());
+        assertThat(shouldDismiss).isTrue();
     }
 
     @Test
-    public void testShouldShowLowBatteryWarning_showStandardOnly_returnsShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.mBatteryLevel = 10;
-        mPowerUI.start();
-
-        // unplugged device that would show the non-hybrid but not the hybrid
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertTrue(shouldShow);
-    }
-
-    @Test
-    public void testShouldShowLowBatteryWarning_deviceHighBattery_returnsNoShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.start();
-
-        // unplugged device that would show the neither due to battery level being good
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
-    }
-
-    @Test
-    public void testShouldShowLowBatteryWarning_devicePlugged_returnsNoShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.start();
-
-        // plugged device that would show the neither due to being plugged
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(!UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
-   }
-
-    @Test
-    public void testShouldShowLowBatteryWarning_deviceBatteryStatusUnknown_returnsNoShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.start();
-
-        // Unknown battery status device that would show the neither due to the battery status being
-        // unknown
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        !POWER_SAVER_OFF, BatteryManager.BATTERY_STATUS_UNKNOWN);
-        assertFalse(shouldShow);
-    }
-
-    @Test
-    public void testShouldShowLowBatteryWarning_batterySaverEnabled_returnsNoShow() {
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        mPowerUI.start();
-
-        // BatterySaverEnabled device that would show the neither due to battery saver
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        !POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
-    }
-
-    @Test
-    public void testShouldShowLowBatteryWarning_onlyShowsOncePerChargeCycle() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        when(mEnhancedEstimates.getEstimate())
-                .thenReturn(new Estimate(BELOW_HYBRID_THRESHOLD, true));
-        mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
-
-        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
-                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
-
-        // reduce battery level to handle time based trigger -> level trigger interactions
-        mPowerUI.mBatteryLevel = 10;
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabledLegacy() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(false);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // device that gets power saver turned on should dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, !POWER_SAVER_OFF);
-        assertTrue(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldNotDismissLowBatteryWarning_dismissWhenPowerSaverEnabledHybrid() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // device that gets power saver turned on should dismiss
-        boolean shouldDismiss =
-            mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, !POWER_SAVER_OFF);
-        assertFalse(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_dismissWhenPlugged() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // device that gets plugged in should dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(!UNPLUGGED, BELOW_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertTrue(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_dismissHybridSignal_showStandardSignal_shouldShow() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // would dismiss hybrid but not non-hybrid should not dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertFalse(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_showHybridSignal_dismissStandardSignal_shouldShow() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // would dismiss non-hybrid but not hybrid should not dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertFalse(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_showBothSignal_shouldShow() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // should not dismiss when both would not dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        BELOW_WARNING_BUCKET, BELOW_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertFalse(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_dismissBothSignal_shouldDismiss() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        //should dismiss if both would dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertTrue(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_dismissStandardSignal_hybridDisabled_shouldDismiss() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(false);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-
-        // would dismiss non-hybrid with hybrid disabled should dismiss
-        boolean shouldDismiss =
-                mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, POWER_SAVER_OFF);
-        assertTrue(shouldDismiss);
-    }
-
-    @Test
-    public void testShouldDismissLowBatteryWarning_powerSaverModeEnabled()
-            throws InterruptedException {
-        when(mPowerManager.isPowerSaveMode()).thenReturn(true);
-
-        mPowerUI.start();
-        mPowerUI.mReceiver.onReceive(mContext,
-                new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
-
-        CountDownLatch latch = new CountDownLatch(1);
-        ThreadUtils.postOnBackgroundThread(() -> latch.countDown());
-        latch.await(5, TimeUnit.SECONDS);
-
-        verify(mMockWarnings).dismissLowBatteryWarning();
-    }
-
-    @Test
-    public void testShouldNotDismissLowBatteryWarning_powerSaverModeDisabled()
-            throws InterruptedException {
-        when(mPowerManager.isPowerSaveMode()).thenReturn(false);
-
-        mPowerUI.start();
-        mPowerUI.mReceiver.onReceive(mContext,
-                new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
-
-        CountDownLatch latch = new CountDownLatch(1);
-        ThreadUtils.postOnBackgroundThread(() -> latch.countDown());
-        latch.await(5, TimeUnit.SECONDS);
-
-        verify(mMockWarnings, never()).dismissLowBatteryWarning();
-    }
-
-    @Test
-    public void testSevereWarning_countsAsLowAndSevere_WarningOnlyShownOnce() {
-        mPowerUI.start();
-        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
-        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
-        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
-        when(mEnhancedEstimates.getEstimate())
-                .thenReturn(new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true));
-        mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
-
-        // reduce battery level to handle time based trigger -> level trigger interactions
-        mPowerUI.mBatteryLevel = 5;
-        boolean shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, BELOW_SEVERE_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertTrue(shouldShow);
-
-        // actually run the end to end since it handles changing the internal state.
-        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_10, UNPLUGGED, UNPLUGGED,
-                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
-
-        shouldShow =
-                mPowerUI.shouldShowLowBatteryWarning(UNPLUGGED, UNPLUGGED, ABOVE_WARNING_BUCKET,
-                        ABOVE_WARNING_BUCKET, VERY_BELOW_SEVERE_HYBRID_THRESHOLD,
-                        POWER_SAVER_OFF, BatteryManager.BATTERY_HEALTH_GOOD);
-        assertFalse(shouldShow);
-    }
-
-    @Test
-    public void testMaybeShowBatteryWarning_onlyQueriesEstimateOnBatteryLevelChangeOrNull() {
+    public void testRefreshEstimateIfNeeded_onlyQueriesEstimateOnBatteryLevelChangeOrNull() {
         mPowerUI.start();
         Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true);
         when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true);
         when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);
         when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS);
         when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
-        mPowerUI.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+        mPowerUI.mBatteryLevel = 10;
 
-        // we expect that the first time it will query even if the level is the same
+        // we expect that the first time it will query since there is no last battery snapshot.
+        // However an invalid estimate (-1) is returned.
+        Estimate refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
+        assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_HYBRID_THRESHOLD);
+        BatteryStateSnapshot snapshot = new BatteryStateSnapshot(
+                BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD,
+                0, 0, -1, 0, 0, false);
+        mPowerUI.mLastBatteryStateSnapshot = snapshot;
+
+        // query again since the estimate was -1
+        estimate = new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true);
+        when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
+        refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
+        assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD);
+        snapshot = new BatteryStateSnapshot(
+                BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD, 0,
+                0, BELOW_SEVERE_HYBRID_THRESHOLD, 0, 0, false);
+        mPowerUI.mLastBatteryStateSnapshot = snapshot;
+
+        // Battery level hasn't changed, so we don't query again
+        estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true);
+        when(mEnhancedEstimates.getEstimate()).thenReturn(estimate);
+        refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
+        assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD);
+
+        // Battery level changes so we update again
         mPowerUI.mBatteryLevel = 9;
-        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
-                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
-        verify(mEnhancedEstimates, times(1)).getEstimate();
+        refreshedEstimate = mPowerUI.refreshEstimateIfNeeded();
+        assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_HYBRID_THRESHOLD);
+    }
 
-        // We should NOT query again if the battery level hasn't changed
-        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_NINE, UNPLUGGED, UNPLUGGED,
-                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
-        verify(mEnhancedEstimates, times(1)).getEstimate();
+    @Test
+    public void testShouldShowStandardWarning() {
+        mPowerUI.start();
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
+        state.mIsHybrid = false;
+        BatteryStateSnapshot lastState = state.get();
 
-        // Battery level has changed, so we should query again
-        mPowerUI.maybeShowBatteryWarning(OLD_BATTERY_LEVEL_10, UNPLUGGED, UNPLUGGED,
-                ABOVE_WARNING_BUCKET, ABOVE_WARNING_BUCKET);
-        verify(mEnhancedEstimates, times(2)).getEstimate();
+        // sanity check to make sure we can show for a valid config
+        state.mBatteryLevel = 10;
+        state.mBucket = -1;
+        boolean shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isTrue();
+        lastState = state.get();
+
+        // Shouldn't show if plugged in
+        state.mPlugged = true;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isFalse();
+
+        state.mPlugged = false;
+        // Shouldn't show if battery saver
+        state.mIsPowerSaver = true;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isFalse();
+
+        state.mIsPowerSaver = false;
+        // Shouldn't show if battery is unknown
+        state.mPlugged = false;
+        state.mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isFalse();
+
+        state.mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+        // show if plugged -> unplugged, bucket -1 -> -1
+        state.mPlugged = true;
+        state.mBucket = -1;
+        lastState = state.get();
+        state.mPlugged = false;
+        state.mBucket = -1;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isTrue();
+
+        // don't show if plugged -> unplugged, bucket 0 -> 0
+        state.mPlugged = true;
+        state.mBucket = 0;
+        lastState = state.get();
+        state.mPlugged = false;
+        state.mBucket = 0;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isFalse();
+
+        // show if unplugged -> unplugged, bucket 0 -> -1
+        state.mPlugged = false;
+        state.mBucket = 0;
+        lastState = state.get();
+        state.mPlugged = false;
+        state.mBucket = -1;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isTrue();
+
+        // don't show if unplugged -> unplugged, bucket -1 -> 1
+        state.mPlugged = false;
+        state.mBucket = -1;
+        lastState = state.get();
+        state.mPlugged = false;
+        state.mBucket = 1;
+        shouldShow = mPowerUI.shouldShowLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldShow).isFalse();
+    }
+
+    @Test
+    public void testShouldDismissStandardWarning() {
+        mPowerUI.start();
+        BatteryStateSnapshotWrapper state = new BatteryStateSnapshotWrapper();
+        state.mIsHybrid = false;
+        BatteryStateSnapshot lastState = state.get();
+
+        // should dismiss if battery saver
+        state.mIsPowerSaver = true;
+        boolean shouldDismiss = mPowerUI.shouldDismissLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldDismiss).isTrue();
+
+        state.mIsPowerSaver = false;
+        // should dismiss if plugged
+        state.mPlugged = true;
+        shouldDismiss = mPowerUI.shouldDismissLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldDismiss).isTrue();
+
+        state.mPlugged = false;
+        // should dismiss if bucket 0 -> 1
+        state.mBucket = 0;
+        lastState = state.get();
+        state.mBucket = 1;
+        shouldDismiss = mPowerUI.shouldDismissLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldDismiss).isTrue();
+
+        // shouldn't dismiss if bucket -1 -> 0
+        state.mBucket = -1;
+        lastState = state.get();
+        state.mBucket = 0;
+        shouldDismiss = mPowerUI.shouldDismissLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldDismiss).isFalse();
+
+        // should dismiss if powersaver & bucket 0 -> 1
+        state.mIsPowerSaver = true;
+        state.mBucket = 0;
+        lastState = state.get();
+        state.mBucket = 1;
+        shouldDismiss = mPowerUI.shouldDismissLowBatteryWarning(state.get(), lastState);
+        assertThat(shouldDismiss).isTrue();
     }
 
     private Temperature getEmergencyStatusTemp(int type, String name) {
@@ -556,4 +518,35 @@
         mPowerUI.mComponents = mContext.getComponents();
         mPowerUI.mThermalService = mThermalServiceMock;
     }
+
+    /**
+     * A simple wrapper class that sets values by default and makes them not final to improve
+     * test clarity.
+     */
+    private class BatteryStateSnapshotWrapper {
+        public int mBatteryLevel = 100;
+        public boolean mIsPowerSaver = false;
+        public boolean mPlugged = false;
+        public long mSevereThresholdMillis = Duration.ofHours(1).toMillis();
+        public long mLowThresholdMillis = Duration.ofHours(3).toMillis();
+        public int mSevereLevelThreshold = 5;
+        public int mLowLevelThreshold = 15;
+        public int mBucket = 1;
+        public int mBatteryStatus = BatteryManager.BATTERY_HEALTH_GOOD;
+        public long mTimeRemainingMillis = Duration.ofHours(24).toMillis();
+        public boolean mIsBasedOnUsage = true;
+        public boolean mIsHybrid = true;
+
+        public BatteryStateSnapshot get() {
+            if (mIsHybrid) {
+                return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket,
+                        mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold,
+                        mTimeRemainingMillis, mSevereThresholdMillis, mLowThresholdMillis,
+                        mIsBasedOnUsage);
+            } else {
+                return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket,
+                        mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 1783d9d..6033ed2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -264,7 +264,8 @@
         val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
                 PrivacyApplication("", TEST_UID, mContext)))
         privacyItemController.privacyList = list
-        assertEquals(list, privacyItemController.privacyList)
-        assertTrue(list !== privacyItemController.privacyList)
+        val privacyList = privacyItemController.privacyList
+        assertEquals(list, privacyList)
+        assertTrue(list !== privacyList)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 12eed78..9e226f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -14,12 +14,14 @@
 
 package com.android.systemui.qs.customize;
 
+import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.atLeastOnce;
@@ -29,8 +31,13 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -48,7 +55,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -68,6 +77,8 @@
     private static final String STOCK_TILES = "wifi,dnd,cell,battery";
     private static final String ALL_TILES = "wifi,dnd,nfc,cell,battery";
     private static final Set<String> FACTORY_TILES = new ArraySet<>();
+    private static final String TEST_PKG = "test_pkg";
+    private static final String TEST_CLS = "test_cls";
 
     static {
         FACTORY_TILES.addAll(Arrays.asList(
@@ -82,6 +93,8 @@
     private QSTileHost mQSTileHost;
     @Mock
     private PackageManager mPackageManager;
+    @Captor
+    private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
 
     private QSTile.State mState;
     private TestableLooper mBGLooper;
@@ -154,8 +167,6 @@
 
     @Test
     public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() {
-        ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
-
         Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
                 ONLY_STOCK_TILES);
         mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
@@ -166,9 +177,9 @@
         mBGLooper.processAllMessages();
         waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
 
-        verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+        verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
-        for (TileQueryHelper.TileInfo t : captor.getValue()) {
+        for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
             specs.add(t.spec);
         }
         String tiles = TextUtils.join(",", specs);
@@ -177,8 +188,6 @@
 
     @Test
     public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() {
-        ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
-
         Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
                 CURRENT_TILES);
         mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
@@ -189,9 +198,9 @@
         mBGLooper.processAllMessages();
         waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
 
-        verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+        verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
-        for (TileQueryHelper.TileInfo t : captor.getValue()) {
+        for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
             specs.add(t.spec);
         }
         String tiles = TextUtils.join(",", specs);
@@ -200,8 +209,6 @@
 
     @Test
     public void testQueryTiles_otherTileNotIncluded() {
-        ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
-
         Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
                 WITH_OTHER_TILES);
         mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
@@ -212,15 +219,44 @@
         mBGLooper.processAllMessages();
         waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
 
-        verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+        verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
         List<String> specs = new ArrayList<>();
-        for (TileQueryHelper.TileInfo t : captor.getValue()) {
+        for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
             specs.add(t.spec);
         }
         assertFalse(specs.contains("other"));
     }
 
     @Test
+    public void testThirdPartyTilesInactive() {
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = mock(ServiceInfo.class, Answers.RETURNS_MOCKS);
+        resolveInfo.serviceInfo = serviceInfo;
+        serviceInfo.packageName = TEST_PKG;
+        serviceInfo.name = TEST_CLS;
+        serviceInfo.icon = R.drawable.android;
+        serviceInfo.permission = Manifest.permission.BIND_QUICK_SETTINGS_TILE;
+        serviceInfo.applicationInfo = mock(ApplicationInfo.class, Answers.RETURNS_MOCKS);
+        serviceInfo.applicationInfo.icon = R.drawable.android;
+        List<ResolveInfo> list = new ArrayList<>();
+        list.add(resolveInfo);
+        when(mPackageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(list);
+
+        Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, "");
+        mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
+                "");
+
+        mTileQueryHelper.queryTiles(mQSTileHost);
+        mBGLooper.processAllMessages();
+        waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+
+        verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
+        List<TileQueryHelper.TileInfo> tileInfos = mCaptor.getValue();
+        assertEquals(1, tileInfos.size());
+        assertEquals(Tile.STATE_INACTIVE, tileInfos.get(0).state.state);
+    }
+
+    @Test
     public void testQueryTiles_nullSetting() {
         Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
         mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index eb465676..22d2585 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -51,13 +51,6 @@
     }
 
     @Test
-    public void testGetMaxAllowedVisibleChildren_ambient() {
-        mGroup.setOnAmbient(true);
-        Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
-            NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_AMBIENT);
-    }
-
-    @Test
     public void testGetMaxAllowedVisibleChildren_lowPriority() {
         mChildrenContainer.setIsLowPriority(true);
         Assert.assertEquals(mChildrenContainer.getMaxAllowedVisibleChildren(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index f88b64a..6db3624 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -37,12 +37,10 @@
 import android.app.AlarmManager;
 import android.graphics.Color;
 import android.os.Handler;
-import android.os.Looper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.View;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
@@ -78,6 +76,7 @@
     private WakeLock mWakeLock;
     private boolean mAlwaysOnEnabled;
     private AlarmManager mAlarmManager;
+    private TestableLooper mLooper;
 
 
     @Before
@@ -88,6 +87,7 @@
         mAlarmManager = mock(AlarmManager.class);
         mAlwaysOnEnabled = true;
         mDozeParamenters = mock(DozeParameters.class);
+        mLooper = TestableLooper.get(this);
         when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled);
         when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true);
         mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront,
@@ -253,7 +253,6 @@
         assertScrimTint(mScrimBehind, false /* tinted */);
     }
 
-    @FlakyTest(bugId = 124858892)
     @Test
     public void transitionToUnlocked() {
         mScrimController.setPanelExpansion(0f);
@@ -298,7 +297,6 @@
         Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
     }
 
-    @FlakyTest(bugId = 124858892)
     @Test
     public void panelExpansion() {
         mScrimController.setPanelExpansion(0f);
@@ -321,7 +319,6 @@
                 mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
     }
 
-    @FlakyTest(bugId = 124858892)
     @Test
     public void panelExpansionAffectsAlpha() {
         mScrimController.setPanelExpansion(0f);
@@ -666,7 +663,6 @@
      */
     private class SynchronousScrimController extends ScrimController {
 
-        private FakeHandler mHandler;
         private boolean mAnimationCancelled;
         boolean mOnPreDrawCalled;
 
@@ -676,7 +672,6 @@
                 AlarmManager alarmManager) {
             super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener,
                     dozeParameters, alarmManager);
-            mHandler = new FakeHandler(Looper.myLooper());
         }
 
         @Override
@@ -688,13 +683,10 @@
         void finishAnimationsImmediately() {
             boolean[] animationFinished = {false};
             setOnAnimationFinished(()-> animationFinished[0] = true);
-
             // Execute code that will trigger animations.
             onPreDraw();
-
-            // Force finish screen blanking.
-            mHandler.dispatchQueuedMessages();
             // Force finish all animations.
+            mLooper.processAllMessages();
             endAnimation(mScrimBehind, TAG_KEY_ANIM);
             endAnimation(mScrimInFront, TAG_KEY_ANIM);
 
@@ -724,7 +716,7 @@
 
         @Override
         protected Handler getHandler() {
-            return mHandler;
+            return new FakeHandler(mLooper.getLooper());
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
new file mode 100644
index 0000000..3e4c4d6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HotspotControllerImplTest extends SysuiTestCase {
+
+    @Mock
+    private ConnectivityManager mConnectivityManager;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private HotspotController.Callback mCallback1;
+    @Mock
+    private HotspotController.Callback mCallback2;
+    private HotspotControllerImpl mController;
+    private TestableLooper mLooper;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mLooper = TestableLooper.get(this);
+
+        mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
+        mContext.addMockSystemService(WifiManager.class, mWifiManager);
+
+        doAnswer((InvocationOnMock invocation) -> {
+            ((WifiManager.SoftApCallback) invocation.getArgument(0)).onNumClientsChanged(1);
+            return null;
+        }).when(mWifiManager).registerSoftApCallback(any(WifiManager.SoftApCallback.class),
+                any(Handler.class));
+
+        mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper()));
+    }
+
+    @Test
+    public void testAddingTwoCallbacksRegistersToWifiManagerOnce() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        verify(mWifiManager, times(1)).registerSoftApCallback(eq(mController), any());
+    }
+
+    @Test
+    public void testAddingCallbacksDoesntUpdateAll() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        mLooper.processAllMessages();
+        // Each callback should be updated only once
+        verify(mCallback1, times(1)).onHotspotChanged(anyBoolean(), anyInt());
+        verify(mCallback2, times(1)).onHotspotChanged(anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void testRemovingTwoCallbacksUnegistersToWifiManagerOnce() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        mController.removeCallback(mCallback1);
+        mController.removeCallback(mCallback2);
+
+        verify(mWifiManager, times(1)).unregisterSoftApCallback(mController);
+    }
+
+    @Test
+    public void testDoNotUnregisterIfRemainingCallbacks() {
+        mController.addCallback(mCallback1);
+        mController.addCallback(mCallback2);
+
+        verify(mWifiManager, never()).unregisterSoftApCallback(any());
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
index 13651a5..de1072d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -11,19 +11,23 @@
  * 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.systemui.statusbar.policy;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Icon;
 import android.service.notification.StatusBarNotification;
 import android.util.Pair;
@@ -34,6 +38,9 @@
 
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.shared.system.PackageManagerWrapper;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions;
 
@@ -50,19 +57,19 @@
 @RunWith(AndroidJUnit4.class)
 public class InflatedSmartRepliesTest extends SysuiTestCase {
 
-    private static final String TEST_ACTION = "com.android.SMART_REPLY_VIEW_ACTION";
+    private static final Intent TEST_INTENT = new Intent("com.android.SMART_REPLY_VIEW_ACTION");
+    private static final Intent WHITELISTED_TEST_INTENT =
+            new Intent("com.android.WHITELISTED_TEST_ACTION");
 
-    @Mock
-    SmartReplyConstants mSmartReplyConstants;
-    @Mock
-    StatusBarNotification mStatusBarNotification;
-    @Mock
-    Notification mNotification;
+    @Mock SmartReplyConstants mSmartReplyConstants;
+    @Mock StatusBarNotification mStatusBarNotification;
+    @Mock Notification mNotification;
     NotificationEntry mEntry;
-    @Mock
-    RemoteInput mRemoteInput;
-    @Mock
-    RemoteInput mFreeFormRemoteInput;
+    @Mock RemoteInput mRemoteInput;
+    @Mock RemoteInput mFreeFormRemoteInput;
+    @Mock ActivityManagerWrapper mActivityManagerWrapper;
+    @Mock PackageManagerWrapper mPackageManagerWrapper;
+    @Mock DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
 
     private Icon mActionIcon;
 
@@ -71,11 +78,18 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        mDependency.injectTestDependency(ActivityManagerWrapper.class, mActivityManagerWrapper);
+        mDependency.injectTestDependency(
+                DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper);
+        mDependency.injectTestDependency(PackageManagerWrapper.class, mPackageManagerWrapper);
+
         when(mNotification.getAllowSystemGeneratedContextualActions()).thenReturn(true);
         when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
         mEntry = new NotificationEntry(mStatusBarNotification);
         when(mSmartReplyConstants.isEnabled()).thenReturn(true);
         mActionIcon = Icon.createWithResource(mContext, R.drawable.ic_person);
+
+        when(mActivityManagerWrapper.isLockTaskKioskModeActive()).thenReturn(false);
     }
 
     @Test
@@ -227,6 +241,87 @@
         assertThat(repliesAndActions.smartReplies).isNull();
     }
 
+    @Test
+    public void chooseSmartRepliesAndActions_lockTaskKioskModeEnabled_smartRepliesUnaffected() {
+        when(mActivityManagerWrapper.isLockTaskKioskModeActive()).thenReturn(true);
+        // No apps are white-listed
+        when(mDevicePolicyManagerWrapper.isLockTaskPermitted(anyString())).thenReturn(false);
+
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // suggestions.
+        setupAppGeneratedReplies(null /* smartReplies */);
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
+                mEntry.systemGeneratedSmartReplies);
+        // Since no apps are whitelisted no actions should be shown.
+        assertThat(repliesAndActions.smartActions.actions).isEmpty();
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_lockTaskKioskModeEnabled_smartActionsAffected() {
+        when(mActivityManagerWrapper.isLockTaskKioskModeActive()).thenReturn(true);
+        String allowedPackage = "allowedPackage";
+        ResolveInfo allowedResolveInfo = new ResolveInfo();
+        allowedResolveInfo.activityInfo = new ActivityInfo();
+        allowedResolveInfo.activityInfo.packageName = allowedPackage;
+        when(mPackageManagerWrapper
+                .resolveActivity(
+                        argThat(intent -> WHITELISTED_TEST_INTENT.getAction().equals(
+                                intent.getAction())),
+                        anyInt() /* flags */))
+                .thenReturn(allowedResolveInfo);
+        when(mDevicePolicyManagerWrapper.isLockTaskPermitted(allowedPackage)).thenReturn(true);
+
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // suggestions.
+        setupAppGeneratedReplies(null /* smartReplies */);
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        List<Notification.Action> actions = new ArrayList<>();
+        actions.add(createAction("allowed action", WHITELISTED_TEST_INTENT));
+        actions.add(createAction("non-allowed action", TEST_INTENT));
+        mEntry.systemGeneratedSmartActions = actions;
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        // Only the action for the whitelisted package should be allowed.
+        assertThat(repliesAndActions.smartActions.actions.size()).isEqualTo(1);
+        assertThat(repliesAndActions.smartActions.actions.get(0)).isEqualTo(
+                mEntry.systemGeneratedSmartActions.get(0));
+    }
+
+    @Test
+    public void chooseSmartRepliesAndActions_screenPinningModeEnabled_suggestionsUnaffected() {
+        when(mActivityManagerWrapper.isLockToAppActive()).thenReturn(true);
+        // No apps are white-listed
+        when(mDevicePolicyManagerWrapper.isLockTaskPermitted(anyString())).thenReturn(false);
+
+        // Pass a null-array as app-generated smart replies, so that we use NAS-generated smart
+        // suggestions.
+        setupAppGeneratedReplies(null /* smartReplies */);
+        mEntry.systemGeneratedSmartReplies =
+                new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+        mEntry.systemGeneratedSmartActions =
+                createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
+
+        SmartRepliesAndActions repliesAndActions =
+                InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+        // We don't restrict replies or actions in screen pinning mode.
+        assertThat(repliesAndActions.smartReplies.choices).isEqualTo(
+                mEntry.systemGeneratedSmartReplies);
+        assertThat(repliesAndActions.smartActions.actions).isEqualTo(
+                mEntry.systemGeneratedSmartActions);
+    }
+
     private void setupAppGeneratedReplies(CharSequence[] smartReplies) {
         setupAppGeneratedReplies(smartReplies, true /* allowSystemGeneratedReplies */);
     }
@@ -234,7 +329,7 @@
     private void setupAppGeneratedReplies(
             CharSequence[] smartReplies, boolean allowSystemGeneratedReplies) {
         PendingIntent pendingIntent =
-                PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), 0);
+                PendingIntent.getBroadcast(mContext, 0, TEST_INTENT, 0);
         Notification.Action action =
                 new Notification.Action.Builder(null, "Test Action", pendingIntent).build();
         when(mRemoteInput.getChoices()).thenReturn(smartReplies);
@@ -261,8 +356,11 @@
     }
 
     private Notification.Action.Builder createActionBuilder(String actionTitle) {
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
-                new Intent(TEST_ACTION), 0);
+        return createActionBuilder(actionTitle, TEST_INTENT);
+    }
+
+    private Notification.Action.Builder createActionBuilder(String actionTitle, Intent intent) {
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
         return new Notification.Action.Builder(mActionIcon, actionTitle, pendingIntent);
     }
 
@@ -270,6 +368,10 @@
         return createActionBuilder(actionTitle).build();
     }
 
+    private Notification.Action createAction(String actionTitle, Intent intent) {
+        return createActionBuilder(actionTitle, intent).build();
+    }
+
     private List<Notification.Action> createActions(String[] actionTitles) {
         List<Notification.Action> actions = new ArrayList<>();
         for (String title : actionTitles) {
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 7ce13c2..a15e89c 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -25,12 +25,15 @@
 	DisplayCutoutEmulationTallOverlay \
 	FontNotoSerifSourceOverlay \
 	IconPackCircularAndroidOverlay \
+	IconPackCircularLauncherOverlay \
 	IconPackCircularSettingsOverlay \
 	IconPackCircularSystemUIOverlay \
 	IconPackFilledAndroidOverlay \
+	IconPackFilledLauncherOverlay \
 	IconPackFilledSettingsOverlay \
 	IconPackFilledSystemUIOverlay \
 	IconPackRoundedAndroidOverlay \
+	IconPackRoundedLauncherOverlay \
 	IconPackRoundedSettingsOverlay \
 	IconPackRoundedSystemUIOverlay \
 	IconShapeRoundedRectOverlay \
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/Android.mk b/packages/overlays/IconPackCircularLauncherOverlay/Android.mk
new file mode 100644
index 0000000..a5277fa
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+#  Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackCircularLauncher
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackCircularLauncherOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/AndroidManifest.xml b/packages/overlays/IconPackCircularLauncherOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..0b69eca
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.theme.icon_pack.circular.launcher"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <overlay android:targetPackage="com.android.launcher3" android:category="android.theme.customization.icon_pack.launcher" android:priority="1"/>
+    <application android:label="Circular" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_clear.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..74ed9ed
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_clear.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9,20h6c1.66,0,3-1.34,3-3V6h0.5c0.41,0,0.75-0.34,0.75-0.75S18.91,4.5,18.5,4.5H18h-3l-1-1h-4l-1,1H6H5.5 c-0.41,0-0.75,0.34-0.75,0.75S5.09,6,5.5,6H6v11C6,18.66,7.34,20,9,20z M16.5,6v11c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V6H16.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M13.97,16c0.41,0,0.75-0.34,0.75-0.75v-6.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v6.5 C13.22,15.66,13.55,16,13.97,16z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,16c0.41,0,0.75-0.34,0.75-0.75v-6.5C10.75,8.34,10.41,8,10,8S9.25,8.34,9.25,8.75v6.5C9.25,15.66,9.59,16,10,16z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml
new file mode 100644
index 0000000..6c4e1de
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_corp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M16,4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H2v12c0,1.66,1.34,3,3,3h14c1.66,0,3-1.34,3-3V6h-6V4z M9.5,4 c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5v2h-5V4z M20.5,7.5V18c0,0.83-0.67,1.5-1.5,1.5H5c-0.83,0-1.5-0.67-1.5-1.5V7.5 H20.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_empty_recents.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_empty_recents.xml
new file mode 100644
index 0000000..7e363f6
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_empty_recents.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M17,18V6c0-1.1-0.9-2-2-2H9C7.9,4,7,4.9,7,6v12c0,1.1,0.9,2,2,2h6C16.1,20,17,19.1,17,18z M8.5,18V6 c0-0.28,0.22-0.5,0.5-0.5h6c0.28,0,0.5,0.22,0.5,0.5v12c0,0.28-0.22,0.5-0.5,0.5H9C8.72,18.5,8.5,18.28,8.5,18z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21,7h-2c-0.55,0-1,0.45-1,1v8c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1V8C22,7.45,21.55,7,21,7z M20.5,15.5h-1v-7h1V15.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M5,17c0.55,0,1-0.45,1-1V8c0-0.55-0.45-1-1-1H3C2.45,7,2,7.45,2,8v8c0,0.55,0.45,1,1,1H5z M3.5,8.5h1v7h-1V8.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml
new file mode 100644
index 0000000..e4bc8e6
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12C22,6.48,17.52,2,11.99,2z M11.99,20.5 c-4.68,0-8.49-3.81-8.49-8.5c0-4.69,3.81-8.5,8.49-8.5c4.69,0,8.51,3.81,8.51,8.5C20.5,16.69,16.68,20.5,11.99,20.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
new file mode 100644
index 0000000..c104e3e
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M3.97,20.03c0.15,0.15,0.34,0.22,0.53,0.22s0.38-0.07,0.53-0.22L12,13.06l6.97,6.97c0.15,0.15,0.34,0.22,0.53,0.22 s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L13.06,12l6.97-6.97c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0L12,10.94 L5.03,3.97c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L10.94,12l-6.97,6.97C3.68,19.26,3.68,19.74,3.97,20.03z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
new file mode 100644
index 0000000..e526329
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,8.5c-1.93,0-3.5,1.57-3.5,3.5s1.57,3.5,3.5,3.5c1.93,0,3.5-1.57,3.5-3.5S13.93,8.5,12,8.5z M12,14c-1.1,0-2-0.9-2-2 s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,14,12,14z M21.29,13.9l-1.83-1.05c-0.3-0.17-0.49-0.49-0.48-0.84v-0.01 c0-0.35,0.18-0.67,0.48-0.84l1.83-1.05c0.48-0.28,0.64-0.89,0.37-1.37l-2-3.46c-0.19-0.32-0.52-0.5-0.87-0.5 c-0.17,0-0.34,0.04-0.5,0.13l-1.84,1.06c-0.14,0.08-0.29,0.12-0.45,0.12c-0.17,0-0.35-0.05-0.5-0.14c0,0-0.01,0-0.01-0.01 C15.2,5.77,15,5.47,15,5.12V3c0-0.55-0.45-1-1-1h-4C9.45,2,9,2.45,9,3v2.12c0,0.34-0.2,0.65-0.5,0.82c0,0-0.01,0-0.01,0.01 c-0.16,0.09-0.33,0.14-0.5,0.14c-0.15,0-0.31-0.04-0.45-0.12L5.71,4.9c-0.16-0.09-0.33-0.13-0.5-0.13c-0.35,0-0.68,0.18-0.87,0.5 l-2,3.46C2.06,9.21,2.23,9.82,2.71,10.1l1.83,1.05c0.3,0.17,0.49,0.49,0.48,0.84v0.01c0,0.35-0.18,0.67-0.48,0.84L2.71,13.9 c-0.48,0.28-0.64,0.89-0.37,1.37l2,3.46c0.19,0.32,0.52,0.5,0.87,0.5c0.17,0,0.34-0.04,0.5-0.13l1.84-1.06 c0.14-0.08,0.29-0.12,0.45-0.12c0.17,0,0.35,0.05,0.5,0.14c0,0,0.01,0,0.01,0.01C8.8,18.23,9,18.53,9,18.88V21c0,0.55,0.45,1,1,1h4 c0.55,0,1-0.45,1-1v-2.12c0-0.34,0.2-0.65,0.5-0.82c0,0,0.01,0,0.01-0.01c0.16-0.09,0.33-0.14,0.5-0.14c0.15,0,0.31,0.04,0.45,0.12 l1.84,1.06c0.16,0.09,0.33,0.13,0.5,0.13c0.35,0,0.68-0.18,0.87-0.5l2-3.46C21.94,14.79,21.77,14.18,21.29,13.9z M18.61,17.55 l-1.41-0.81c-0.36-0.21-0.78-0.32-1.2-0.32c-0.43,0-0.86,0.12-1.25,0.34c-0.77,0.44-1.25,1.25-1.25,2.12v1.62h-3v-1.62 c0-0.87-0.48-1.68-1.26-2.12c-0.38-0.22-0.81-0.33-1.25-0.33c-0.42,0-0.84,0.11-1.2,0.32l-1.41,0.81l-1.5-2.6l1.39-0.8 c0.76-0.44,1.24-1.26,1.23-2.15c0-0.88-0.47-1.7-1.23-2.14l-1.39-0.8l1.5-2.6L6.8,7.26c0.36,0.21,0.78,0.32,1.2,0.32 c0.43,0,0.86-0.12,1.25-0.34c0.77-0.44,1.25-1.25,1.25-2.12V3.5h3v1.62c0,0.87,0.48,1.68,1.26,2.12c0.38,0.22,0.81,0.33,1.25,0.33 c0.42,0,0.84-0.11,1.2-0.32l1.41-0.81l1.5,2.6l-1.39,0.8c-0.76,0.44-1.24,1.26-1.23,2.15c0,0.88,0.47,1.7,1.23,2.14l1.39,0.8 L18.61,17.55z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
new file mode 100644
index 0000000..78de832
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M15.08,8.01c-0.39-0.39-0.91-0.59-1.42-0.59c-0.51,0-1.02,0.2-1.41,0.59L0.59,19.67l3.75,3.75l11.66-11.66 c0.78-0.78,0.78-2.04,0.01-2.82L15.08,8.01z M4.34,21.29l-1.63-1.63l7.45-7.45l1.63,1.63L4.34,21.29z M14.93,10.7l-2.09,2.09 l-1.63-1.63l2.09-2.09c0.13-0.13,0.28-0.15,0.35-0.15c0.08,0,0.23,0.02,0.36,0.15l0.92,0.93C15.13,10.18,15.13,10.5,14.93,10.7z M17.67,5.25h1.08v1.08c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V5.25h1.08c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.08V2.67c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.08h-1.08c-0.41,0-0.75,0.34-0.75,0.75 S17.26,5.25,17.67,5.25z M5.67,5.25h1.08v1.08c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75V5.25h1.08 c0.41,0,0.75-0.34,0.75-0.75S9.74,3.75,9.33,3.75H8.25V2.67c0-0.41-0.34-0.75-0.75-0.75S6.75,2.26,6.75,2.67v1.08H5.67 c-0.41,0-0.75,0.34-0.75,0.75S5.26,5.25,5.67,5.25z M21.33,15.75h-1.08v-1.08c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75 v1.08h-1.08c-0.41,0-0.75,0.34-0.75,0.75s0.34,0.75,0.75,0.75h1.08v1.08c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.08 h1.08c0.41,0,0.75-0.34,0.75-0.75S21.74,15.75,21.33,15.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml
new file mode 100644
index 0000000..11f0b4b
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4,6v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V6c0-1.1-0.9-2-2-2H6C4.9,4,4,4.9,4,6z M18.5,6v3c0,0.28-0.22,0.5-0.5,0.5H6 C5.72,9.5,5.5,9.28,5.5,9V6c0-0.28,0.22-0.5,0.5-0.5h12C18.28,5.5,18.5,5.72,18.5,6z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4,18c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3c0-1.1-0.9-2-2-2H6c-1.1,0-2,0.9-2,2V18z M5.5,15c0-0.28,0.22-0.5,0.5-0.5h12 c0.28,0,0.5,0.22,0.5,0.5v3c0,0.28-0.22,0.5-0.5,0.5H6c-0.28,0-0.5-0.22-0.5-0.5V15z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_wallpaper.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_wallpaper.xml
new file mode 100644
index 0000000..3834fb6
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_wallpaper.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <group
+            android:translateX="119.000000"
+            android:translateY="358.000000">
+        <group
+                android:translateX="2.000000"
+                android:translateY="2.000000">
+            <path
+                android:fillColor="#000000"
+                android:pathData="M-109-356.5c4.69,0,8.5,3.36,8.5,7.5c0,2.48-2.02,4.5-4.5,4.5h-1.77c-1.1,0-2,0.9-2,2 c0,0.45,0.16,0.89,0.46,1.27l0.02,0.02l0.02,0.02c0.17,0.2,0.27,0.44,0.27,0.68c0,0.55-0.45,1-1,1c-4.69,0-8.5-3.81-8.5-8.5 S-113.69-356.5-109-356.5 M-109-358c-5.51,0-10,4.49-10,10s4.49,10,10,10c1.38,0,2.5-1.12,2.5-2.5c0-0.61-0.23-1.2-0.64-1.67 c-0.08-0.1-0.13-0.21-0.13-0.33c0-0.28,0.22-0.5,0.5-0.5h1.77c3.31,0,6-2.69,6-6C-99-353.96-103.49-358-109-358L-109-358z" />
+        </group>
+    </group>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 6.5 10 C 7.32842712475 10 8 10.6715728753 8 11.5 C 8 12.3284271247 7.32842712475 13 6.5 13 C 5.67157287525 13 5 12.3284271247 5 11.5 C 5 10.6715728753 5.67157287525 10 6.5 10 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 9.5 6 C 10.3284271247 6 11 6.67157287525 11 7.5 C 11 8.32842712475 10.3284271247 9 9.5 9 C 8.67157287525 9 8 8.32842712475 8 7.5 C 8 6.67157287525 8.67157287525 6 9.5 6 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 14.5 6 C 15.3284271247 6 16 6.67157287525 16 7.5 C 16 8.32842712475 15.3284271247 9 14.5 9 C 13.6715728753 9 13 8.32842712475 13 7.5 C 13 6.67157287525 13.6715728753 6 14.5 6 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 17.5 10 C 18.3284271247 10 19 10.6715728753 19 11.5 C 19 12.3284271247 18.3284271247 13 17.5 13 C 16.6715728753 13 16 12.3284271247 16 11.5 C 16 10.6715728753 16.6715728753 10 17.5 10 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml
new file mode 100644
index 0000000..f73a9cc
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_warning.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4.47,21h15.06c1.54,0,2.5-1.67,1.73-3L13.73,4.99c-0.39-0.67-1.06-1-1.73-1s-1.35,0.33-1.73,1L2.74,18 C1.97,19.33,2.93,21,4.47,21z M4.04,18.75l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25s0.31,0.03,0.43,0.25l7.53,13.01 c0.13,0.22,0.05,0.41,0,0.5c-0.05,0.09-0.18,0.25-0.43,0.25H4.47c-0.25,0-0.38-0.16-0.43-0.25C3.98,19.16,3.91,18.97,4.04,18.75z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,14.75c0.41,0,0.75-0.34,0.75-0.75V9.75C12.75,9.33,12.41,9,12,9s-0.75,0.34-0.75,0.75V14 C11.25,14.41,11.59,14.75,12,14.75z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml
new file mode 100644
index 0000000..1c2470e
--- /dev/null
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_widget.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M11,5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v4c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2V5z M9.5,9c0,0.28-0.22,0.5-0.5,0.5H5 C4.72,9.5,4.5,9.28,4.5,9V5c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5V9z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9,13H5c-1.1,0-2,0.9-2,2v4c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-4C11,13.9,10.1,13,9,13z M9.5,19c0,0.28-0.22,0.5-0.5,0.5 H5c-0.28,0-0.5-0.22-0.5-0.5v-4c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5V19z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M19,13h-4c-1.1,0-2,0.9-2,2v4c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-4C21,13.9,20.1,13,19,13z M19.5,19 c0,0.28-0.22,0.5-0.5,0.5h-4c-0.28,0-0.5-0.22-0.5-0.5v-4c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5V19z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18.41,2.76c-0.39-0.39-0.9-0.59-1.41-0.59s-1.02,0.2-1.41,0.59l-2.83,2.83c-0.78,0.78-0.78,2.05,0,2.83l2.83,2.83 c0.39,0.39,0.9,0.59,1.41,0.59s1.02-0.2,1.41-0.59l2.83-2.83c0.78-0.78,0.78-2.05,0-2.83L18.41,2.76z M20.18,7.35l-2.83,2.83 c-0.13,0.13-0.28,0.15-0.35,0.15s-0.23-0.02-0.35-0.15l-2.83-2.83C13.69,7.23,13.67,7.08,13.67,7s0.02-0.23,0.15-0.35l2.83-2.83 c0.13-0.13,0.28-0.15,0.35-0.15s0.23,0.02,0.35,0.15l2.83,2.83c0.13,0.13,0.15,0.28,0.15,0.35S20.31,7.23,20.18,7.35z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/Android.mk b/packages/overlays/IconPackFilledLauncherOverlay/Android.mk
new file mode 100644
index 0000000..d2e5b60
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+#  Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackFilledLauncher
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackFilledLauncherOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/AndroidManifest.xml b/packages/overlays/IconPackFilledLauncherOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..0b9f636
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.theme.icon_pack.filled.launcher"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <overlay android:targetPackage="com.android.launcher3" android:category="android.theme.customization.icon_pack.launcher" android:priority="1"/>
+    <application android:label="Filled" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_clear.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..1a2f778
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_clear.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,4h-1h-4c0-0.55-0.45-1-1-1h-4C9.45,3,9,3.45,9,4H5H4C3.59,4,3.25,4.34,3.25,4.75S3.59,5.5,4,5.5h1V18 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V5.5h1c0.41,0,0.75-0.34,0.75-0.75S20.41,4,20,4z M17.5,18c0,0.83-0.67,1.5-1.5,1.5H8 c-0.83,0-1.5-0.67-1.5-1.5V5.5h11V18z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M14.25,8c-0.41,0-0.75,0.34-0.75,0.75v7.5c0,0.41,0.34,0.75,0.75,0.75S15,16.66,15,16.25v-7.5C15,8.34,14.66,8,14.25,8z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9.75,8C9.34,8,9,8.34,9,8.75v7.5C9,16.66,9.34,17,9.75,17s0.75-0.34,0.75-0.75v-7.5C10.5,8.34,10.16,8,9.75,8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml
new file mode 100644
index 0000000..8910308
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_corp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,6h-4V4c0-1.1-0.9-2-2-2h-4C8.9,2,8,2.9,8,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8 C22,6.9,21.1,6,20,6z M9.5,4c0-0.28,0.22-0.5,0.5-0.5h4c0.28,0,0.5,0.22,0.5,0.5v2h-5V4z M20.5,19c0,0.28-0.22,0.5-0.5,0.5H4 c-0.28,0-0.5-0.22-0.5-0.5V8c0-0.28,0.22-0.5,0.5-0.5h16c0.28,0,0.5,0.22,0.5,0.5V19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_empty_recents.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_empty_recents.xml
new file mode 100644
index 0000000..1d4c8d7
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_empty_recents.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M17,18V6c0-1.1-0.9-2-2-2H9C7.9,4,7,4.9,7,6v12c0,1.1,0.9,2,2,2h6C16.1,20,17,19.1,17,18z M8.5,18V6 c0-0.28,0.22-0.5,0.5-0.5h6c0.28,0,0.5,0.22,0.5,0.5v12c0,0.28-0.22,0.5-0.5,0.5H9C8.72,18.5,8.5,18.28,8.5,18z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21,17c0.55,0,1-0.45,1-1V8c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1v8c0,0.55,0.45,1,1,1H21z M19.5,8.5h1v7h-1V8.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M5,7H3C2.45,7,2,7.45,2,8v8c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1V8C6,7.45,5.55,7,5,7z M4.5,15.5h-1v-7h1V15.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml
new file mode 100644
index 0000000..a90141d
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4.92,4.94c-3.9,3.91-3.9,10.24,0.01,14.14s10.24,3.9,14.14-0.01C20.95,17.2,22,14.65,22,12c0-2.65-1.06-5.19-2.93-7.07 C15.16,1.03,8.83,1.03,4.92,4.94z M18,18c-1.6,1.59-3.76,2.48-6.02,2.48c-4.69-0.01-8.49-3.83-8.48-8.52 c0.01-4.69,3.83-8.49,8.52-8.48c4.69,0.01,8.49,3.83,8.48,8.52C20.49,14.25,19.6,16.41,18,18z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
new file mode 100644
index 0000000..d31b6a1
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M5.22,18.78C5.37,18.93,5.56,19,5.75,19s0.38-0.07,0.53-0.22L12,13.06l5.72,5.72c0.15,0.15,0.34,0.22,0.53,0.22 s0.38-0.07,0.53-0.22c0.29-0.29,0.29-0.77,0-1.06L13.06,12l5.72-5.72c0.29-0.29,0.29-0.77,0-1.06s-0.77-0.29-1.06,0L12,10.94 L6.28,5.22c-0.29-0.29-0.77-0.29-1.06,0s-0.29,0.77,0,1.06L10.94,12l-5.72,5.72C4.93,18.01,4.93,18.49,5.22,18.78z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
new file mode 100644
index 0000000..70dc701
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M2.43,15.45l1.79,3.09c0.25,0.45,0.74,0.73,1.25,0.73c0.17,0,0.35-0.03,0.52-0.09l1.76-0.7c0.25,0.17,0.51,0.31,0.77,0.45 l0.26,1.84c0.09,0.71,0.69,1.24,1.42,1.24h3.61c0.72,0,1.33-0.53,1.43-1.19l0.26-1.86c0.25-0.14,0.51-0.28,0.76-0.45l1.76,0.7 c0.17,0.07,0.35,0.1,0.53,0.1c0.5,0,0.98-0.27,1.23-0.72l1.82-3.14c0.34-0.61,0.19-1.38-0.36-1.82l-1.48-1.16 c0.01-0.15,0.02-0.29,0.02-0.45s-0.01-0.3-0.02-0.45l1.48-1.16c0.55-0.43,0.7-1.19,0.35-1.84l-1.8-3.1 c-0.25-0.45-0.74-0.73-1.26-0.73c-0.17,0-0.35,0.03-0.52,0.09l-1.76,0.7c-0.25-0.17-0.51-0.31-0.77-0.45l-0.26-1.84 c-0.09-0.71-0.69-1.24-1.42-1.24h-3.61c-0.71,0-1.32,0.54-1.41,1.22L8.52,5.09C8.26,5.23,8.01,5.37,7.75,5.54L5.99,4.83 c-0.17-0.07-0.35-0.1-0.52-0.1c-0.5,0-0.98,0.27-1.22,0.72L2.43,8.55c-0.36,0.61-0.21,1.4,0.36,1.84l1.48,1.16 C4.27,11.7,4.26,11.85,4.26,12c0,0.16,0.01,0.3,0.02,0.45l-1.49,1.16C2.24,14.04,2.09,14.8,2.43,15.45z M5.2,13.63l0.63-0.49 l-0.05-0.79c-0.01-0.11-0.01-0.58,0-0.7l0.05-0.79L5.2,10.37L3.77,9.25l1.74-3l1.69,0.68l0.73,0.29l0.66-0.43 c0.19-0.13,0.4-0.25,0.65-0.38l0.67-0.36L10,5.3l0.25-1.79h3.48l0.26,1.8l0.11,0.76l0.69,0.36c0.23,0.12,0.44,0.24,0.64,0.37 l0.65,0.43l0.72-0.29l1.7-0.68l1.75,3.02l-1.43,1.12l-0.62,0.49l0.05,0.79c0.01,0.11,0.01,0.58,0,0.7l-0.05,0.79l0.62,0.49 l1.43,1.12l-1.74,3.02l-1.69-0.68l-0.72-0.29l-0.65,0.43c-0.19,0.13-0.4,0.25-0.65,0.38l-0.67,0.36l-0.11,0.75l-0.25,1.77h-3.5 L10,18.71l-0.11-0.76l-0.69-0.36c-0.23-0.12-0.44-0.24-0.64-0.37l-0.65-0.43l-0.72,0.29L5.5,17.76l-1.73-3.01L5.2,13.63z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,16c2.21,0,4-1.79,4-4s-1.79-4-4-4c-2.21,0-4,1.79-4,4S9.79,16,12,16z M12,9.5c1.38,0,2.5,1.12,2.5,2.5 s-1.12,2.5-2.5,2.5c-1.38,0-2.5-1.12-2.5-2.5S10.62,9.5,12,9.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
new file mode 100644
index 0000000..d754cbe
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M14.38,7.3C14.18,7.1,13.92,7,13.66,7c-0.26,0-0.51,0.1-0.71,0.29L1.29,18.96c-0.39,0.39-0.39,1.02,0,1.41l2.34,2.34 C3.82,22.9,4.08,23,4.34,23s0.51-0.1,0.71-0.29L16.7,11.05c0.39-0.39,0.39-1.02,0-1.41L14.38,7.3z M4.34,21.29l-1.63-1.63 l7.45-7.45l1.63,1.63L4.34,21.29z M12.84,12.78l-1.63-1.63l2.45-2.45l1.62,1.64L12.84,12.78z M17.75,5.25h1v1 C18.75,6.66,19.09,7,19.5,7s0.75-0.34,0.75-0.75v-1h1C21.66,5.25,22,4.91,22,4.5s-0.34-0.75-0.75-0.75h-1v-1 C20.25,2.34,19.91,2,19.5,2s-0.75,0.34-0.75,0.75v1h-1C17.34,3.75,17,4.09,17,4.5S17.34,5.25,17.75,5.25z M5.75,5.25h1v1 C6.75,6.66,7.09,7,7.5,7s0.75-0.34,0.75-0.75v-1h1C9.66,5.25,10,4.91,10,4.5S9.66,3.75,9.25,3.75h-1v-1C8.25,2.34,7.91,2,7.5,2 S6.75,2.34,6.75,2.75v1h-1C5.34,3.75,5,4.09,5,4.5S5.34,5.25,5.75,5.25z M21.25,15.75h-1v-1c0-0.41-0.34-0.75-0.75-0.75 s-0.75,0.34-0.75,0.75v1h-1c-0.41,0-0.75,0.34-0.75,0.75s0.34,0.75,0.75,0.75h1v1c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75 v-1h1c0.41,0,0.75-0.34,0.75-0.75S21.66,15.75,21.25,15.75z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml
new file mode 100644
index 0000000..87a9546
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M5,11h14c0.55,0,1-0.45,1-1V4c0-0.55-0.45-1-1-1H5C4.45,3,4,3.45,4,4v6C4,10.55,4.45,11,5,11z M5.5,4.5h13v5h-13V4.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4,20c0,0.55,0.45,1,1,1h14c0.55,0,1-0.45,1-1v-6c0-0.55-0.45-1-1-1H5c-0.55,0-1,0.45-1,1V20z M5.5,14.5h13v5h-13V14.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_wallpaper.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_wallpaper.xml
new file mode 100644
index 0000000..3834fb6
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_wallpaper.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <group
+            android:translateX="119.000000"
+            android:translateY="358.000000">
+        <group
+                android:translateX="2.000000"
+                android:translateY="2.000000">
+            <path
+                android:fillColor="#000000"
+                android:pathData="M-109-356.5c4.69,0,8.5,3.36,8.5,7.5c0,2.48-2.02,4.5-4.5,4.5h-1.77c-1.1,0-2,0.9-2,2 c0,0.45,0.16,0.89,0.46,1.27l0.02,0.02l0.02,0.02c0.17,0.2,0.27,0.44,0.27,0.68c0,0.55-0.45,1-1,1c-4.69,0-8.5-3.81-8.5-8.5 S-113.69-356.5-109-356.5 M-109-358c-5.51,0-10,4.49-10,10s4.49,10,10,10c1.38,0,2.5-1.12,2.5-2.5c0-0.61-0.23-1.2-0.64-1.67 c-0.08-0.1-0.13-0.21-0.13-0.33c0-0.28,0.22-0.5,0.5-0.5h1.77c3.31,0,6-2.69,6-6C-99-353.96-103.49-358-109-358L-109-358z" />
+        </group>
+    </group>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 6.5 10 C 7.32842712475 10 8 10.6715728753 8 11.5 C 8 12.3284271247 7.32842712475 13 6.5 13 C 5.67157287525 13 5 12.3284271247 5 11.5 C 5 10.6715728753 5.67157287525 10 6.5 10 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 9.5 6 C 10.3284271247 6 11 6.67157287525 11 7.5 C 11 8.32842712475 10.3284271247 9 9.5 9 C 8.67157287525 9 8 8.32842712475 8 7.5 C 8 6.67157287525 8.67157287525 6 9.5 6 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 14.5 6 C 15.3284271247 6 16 6.67157287525 16 7.5 C 16 8.32842712475 15.3284271247 9 14.5 9 C 13.6715728753 9 13 8.32842712475 13 7.5 C 13 6.67157287525 13.6715728753 6 14.5 6 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 17.5 10 C 18.3284271247 10 19 10.6715728753 19 11.5 C 19 12.3284271247 18.3284271247 13 17.5 13 C 16.6715728753 13 16 12.3284271247 16 11.5 C 16 10.6715728753 16.6715728753 10 17.5 10 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml
new file mode 100644
index 0000000..614828c
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_warning.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4.47,21h15.06c1.54,0,2.5-1.67,1.73-3L13.73,4.99c-0.39-0.67-1.06-1-1.73-1s-1.35,0.33-1.73,1L2.74,18 C1.97,19.33,2.93,21,4.47,21z M4.04,18.75l7.53-13.01c0.13-0.22,0.33-0.25,0.43-0.25s0.31,0.03,0.43,0.25l7.53,13.01 c0.13,0.22,0.05,0.41,0,0.5c-0.05,0.09-0.18,0.25-0.43,0.25H4.47c-0.25,0-0.38-0.16-0.43-0.25C3.98,19.16,3.91,18.97,4.04,18.75z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,14.5c0.41,0,0.75-0.34,0.75-0.75v-4C12.75,9.33,12.41,9,12,9s-0.75,0.34-0.75,0.75v4C11.25,14.16,11.59,14.5,12,14.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml
new file mode 100644
index 0000000..a8aeaf2
--- /dev/null
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_widget.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,3H4C3.45,3,3,3.45,3,4v6c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1V4C11,3.45,10.55,3,10,3z M9.5,9.5h-5v-5h5V9.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,13H4c-0.55,0-1,0.45-1,1v6c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1v-6C11,13.45,10.55,13,10,13z M9.5,19.5h-5v-5h5 V19.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,13h-6c-0.55,0-1,0.45-1,1v6c0,0.55,0.45,1,1,1h6c0.55,0,1-0.45,1-1v-6C21,13.45,20.55,13,20,13z M19.5,19.5h-5v-5h5 V19.5z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21.95,6.29l-4.24-4.24c-0.2-0.2-0.45-0.29-0.71-0.29s-0.51,0.1-0.71,0.29l-4.24,4.24c-0.39,0.39-0.39,1.02,0,1.41 l4.24,4.24c0.2,0.2,0.45,0.29,0.71,0.29s0.51-0.1,0.71-0.29l4.24-4.24C22.34,7.32,22.34,6.68,21.95,6.29z M17,10.54L13.46,7 L17,3.46L20.54,7L17,10.54z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk b/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk
new file mode 100644
index 0000000..7adfe3b
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk
@@ -0,0 +1,31 @@
+#
+#  Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := IconPackRoundedLauncher
+LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := IconPackRoundedLauncherOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/AndroidManifest.xml b/packages/overlays/IconPackRoundedLauncherOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..8406f42
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+/**
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.theme.icon_pack.rounded.launcher"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <overlay android:targetPackage="com.android.launcher3" android:category="android.theme.customization.icon_pack.launcher" android:priority="1"/>
+    <application android:label="Rounded" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_clear.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..919e93e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_clear.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18,4h-2.5l-0.71-0.71C14.61,3.11,14.35,3,14.09,3H9.9C9.64,3,9.38,3.11,9.2,3.29L8.49,4h-2.5c-0.55,0-1,0.45-1,1 s0.45,1,1,1h12c0.55,0,1-0.45,1-1C19,4.45,18.55,4,18,4z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml
new file mode 100644
index 0000000..5a14373
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_corp.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,6h-4V4c0-1.11-0.89-2-2-2h-4C8.89,2,8,2.89,8,4v2H4C2.89,6,2.01,6.89,2.01,8L2,19c0,1.11,0.89,2,2,2h16 c1.11,0,2-0.89,2-2V8C22,6.89,21.11,6,20,6z M14,6h-4V4h4V6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_empty_recents.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_empty_recents.xml
new file mode 100644
index 0000000..76f8831
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_empty_recents.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M3,6h2c0.55,0,1,0.45,1,1v9c0,0.55-0.45,1-1,1H3c-0.55,0-1-0.45-1-1V7C2,6.45,2.45,6,3,6z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M8,19h8c0.55,0,1-0.45,1-1V5c0-0.55-0.45-1-1-1H8C7.45,4,7,4.45,7,5v13C7,18.55,7.45,19,8,19z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M19,6h2c0.55,0,1,0.45,1,1v9c0,0.55-0.45,1-1,1h-2c-0.55,0-1-0.45-1-1V7C18,6.45,18.45,6,19,6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml
new file mode 100644
index 0000000..6a4e448
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_info_no_shadow.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M13,17c0,0.55-0.45,1-1,1s-1-0.45-1-1 v-5c0-0.55,0.45-1,1-1s1,0.45,1,1V17z M12,9.25c-0.69,0-1.25-0.56-1.25-1.25S11.31,6.75,12,6.75S13.25,7.31,13.25,8 S12.69,9.25,12,9.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
new file mode 100644
index 0000000..08ae89f
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_remove_no_shadow.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M5.7,18.3c0.39,0.39,1.02,0.39,1.41,0L12,13.41l4.89,4.89c0.39,0.39,1.02,0.39,1.41,0s0.39-1.02,0-1.41L13.41,12l4.89-4.89 c0.38-0.38,0.38-1.02,0-1.4c-0.39-0.39-1.02-0.39-1.41,0c0,0,0,0,0,0L12,10.59L7.11,5.7c-0.39-0.39-1.02-0.39-1.41,0 s-0.39,1.02,0,1.41L10.59,12L5.7,16.89C5.31,17.28,5.31,17.91,5.7,18.3z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
new file mode 100644
index 0000000..842b687
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21.64,8.39l-1.6-2.76c-0.28-0.48-0.88-0.7-1.36-0.5l-2.14,0.91c-0.48-0.37-1.01-0.68-1.57-0.92l-0.27-2.2 C14.64,2.4,14.14,2,13.59,2h-3.18C9.86,2,9.36,2.4,9.3,2.92L9.04,5.11c-0.57,0.24-1.1,0.55-1.58,0.92L5.32,5.12 c-0.48-0.2-1.08,0.02-1.36,0.5l-1.6,2.76C2.08,8.86,2.18,9.48,2.6,9.8l1.94,1.45C4.51,11.49,4.5,11.74,4.5,12s0.01,0.51,0.04,0.76 L2.6,14.2c-0.42,0.31-0.52,0.94-0.24,1.41l1.6,2.76c0.28,0.48,0.88,0.7,1.36,0.5l2.14-0.91c0.48,0.37,1.01,0.68,1.57,0.92 l0.27,2.19C9.36,21.6,9.86,22,10.41,22h3.18c0.55,0,1.04-0.4,1.11-0.92l0.27-2.19c0.56-0.24,1.09-0.55,1.57-0.92l2.14,0.91 c0.48,0.2,1.08-0.02,1.36-0.5l1.6-2.76c0.28-0.48,0.18-1.1-0.24-1.42l-1.94-1.45c0.03-0.25,0.04-0.5,0.04-0.76 s-0.01-0.51-0.04-0.76L21.4,9.8C21.82,9.49,21.92,8.86,21.64,8.39z M12,15.5c-1.93,0-3.5-1.57-3.5-3.5s1.57-3.5,3.5-3.5 s3.5,1.57,3.5,3.5S13.93,15.5,12,15.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
new file mode 100644
index 0000000..8950fbd
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_smartspace_preferences.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21.23,2.43L19.5,3.4l-1.73-0.97c-0.22-0.12-0.46,0.12-0.34,0.34L18.4,4.5l-0.97,1.73c-0.12,0.22,0.12,0.46,0.34,0.34 L19.5,5.6l1.73,0.97c0.22,0.12,0.46-0.12,0.34-0.34L20.6,4.5l0.97-1.73C21.69,2.55,21.45,2.31,21.23,2.43z M14.37,7.29 c-0.39-0.39-1.02-0.39-1.41,0L1.29,18.96c-0.39,0.39-0.39,1.02,0,1.41l2.34,2.34c0.39,0.39,1.02,0.39,1.41,0L16.7,11.05 c0.39-0.39,0.39-1.02,0-1.41L14.37,7.29z M13.34,12.78l-2.12-2.12l2.44-2.44l2.12,2.12L13.34,12.78z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M21.23,14.43L19.5,15.4l-1.73-0.97c-0.22-0.12-0.46,0.12-0.34,0.34l0.97,1.73l-0.97,1.73c-0.12,0.22,0.12,0.46,0.34,0.34 l1.73-0.97l1.73,0.97c0.22,0.12,0.46-0.12,0.34-0.34L20.6,16.5l0.97-1.73C21.69,14.55,21.45,14.31,21.23,14.43z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9.23,2.43L7.5,3.4L5.77,2.43C5.55,2.31,5.31,2.55,5.43,2.77L6.4,4.5L5.43,6.23C5.31,6.45,5.55,6.69,5.77,6.57L7.5,5.6 l1.73,0.97c0.22,0.12,0.46-0.12,0.34-0.34L8.6,4.5l0.97-1.73C9.69,2.55,9.45,2.31,9.23,2.43z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml
new file mode 100644
index 0000000..30478b3
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_split_screen.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18,2H6C4.9,2,4,2.9,4,4v5c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18,13H6c-1.1,0-2,0.9-2,2v5c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-5C20,13.9,19.1,13,18,13z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_wallpaper.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_wallpaper.xml
new file mode 100644
index 0000000..72d1d31
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_wallpaper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,2C6.49,2,2,6.49,2,12s4.49,10,10,10c1.38,0,2.5-1.12,2.5-2.5c0-0.61-0.23-1.2-0.64-1.67c-0.08-0.1-0.13-0.21-0.13-0.33 c0-0.28,0.22-0.5,0.5-0.5H16c3.31,0,6-2.69,6-6C22,6.04,17.51,2,12,2z M6.5,13C5.67,13,5,12.33,5,11.5S5.67,10,6.5,10 S8,10.67,8,11.5S7.33,13,6.5,13z M9.5,9C8.67,9,8,8.33,8,7.5S8.67,6,9.5,6S11,6.67,11,7.5S10.33,9,9.5,9z M14.5,9 C13.67,9,13,8.33,13,7.5S13.67,6,14.5,6S16,6.67,16,7.5S15.33,9,14.5,9z M17.5,13c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5 s1.5,0.67,1.5,1.5S18.33,13,17.5,13z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml
new file mode 100644
index 0000000..f92842a
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_warning.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12.87,3.49c-0.39-0.67-1.35-0.67-1.73,0l-9.27,16C1.48,20.17,1.96,21,2.73,21h18.53c0.77,0,1.25-0.83,0.87-1.5L12.87,3.49 z M11,10c0-0.55,0.45-1,1-1s1,0.45,1,1v3c0,0.55-0.45,1-1,1s-1-0.45-1-1V10z M12,18.25c-0.69,0-1.25-0.56-1.25-1.25 s0.56-1.25,1.25-1.25s1.25,0.56,1.25,1.25S12.69,18.25,12,18.25z" />
+</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml
new file mode 100644
index 0000000..511757f
--- /dev/null
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_widget.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M17.7,2.3c-0.4-0.4-1-0.4-1.4,0l-4,4c-0.4,0.4-0.4,1,0,1.4l4,4c0.4,0.4,1,0.4,1.4,0l4-4c0.4-0.4,0.4-1,0-1.4L17.7,2.3z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M11,4c0-0.5-0.4-1-1-1H4C3.5,3,3,3.5,3,4v6c0,0.6,0.5,1,1,1h6c0.6,0,1-0.4,1-1V4z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,21c0.5,0,1-0.5,1-1v-6c0-0.6-0.5-1-1-1h-6c-0.6,0-1,0.4-1,1v6c0,0.5,0.4,1,1,1H20z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10,13H4c-0.5,0-1,0.4-1,1v6c0,0.5,0.5,1,1,1h6c0.6,0,1-0.5,1-1v-6C11,13.4,10.6,13,10,13z" />
+</vector>
\ No newline at end of file
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 365c6b4..91b161d 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -253,6 +253,13 @@
     MANAGED_PROFILE = 2;
   }
 
+  // Subtypes for showing direct sharing targets
+  enum DirectShareTargetPreviousState {
+    PREVIOUSLY_UNKNOWN = 0;
+    PREVIOUSLY_HIDDEN = 1;
+    PREVIOUSLY_VISIBLE = 2;
+  }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -7065,6 +7072,21 @@
 
     ACTION_ATCHNUC = 1681;
 
+    // OPEN: Accessibility detail settings (android.settings.ACCESSIBILITY_DETAILS_SETTINGS intent)
+    ACCESSIBILITY_DETAILS_SETTINGS = 1682;
+
+    // Open: Settings will show the conditional when Grayscale mode is on
+    SETTINGS_CONDITION_GRAYSCALE_MODE = 1683;
+
+    // ACTION: Individual contextual card loading time
+    ACTION_CONTEXTUAL_CARD_LOAD = 1684;
+
+    //ACTION: Contextual card loading timeout
+    ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT = 1685;
+
+    //ACTION: Log result for each card's eligibility check
+    ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBlur.java b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
index a36873e..0891d51 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -62,6 +62,10 @@
         if (ain.getType().getY() == 0) {
             throw new RSIllegalArgumentException("Input set to a 1D Allocation");
         }
+        Element e = ain.getElement();
+        if ((!e.isCompatible(Element.U8_4(mRS))) && (!e.isCompatible(Element.U8(mRS)))) {
+            throw new RSIllegalArgumentException("Unsupported element type.");
+        }
         mInput = ain;
         setVar(1, ain);
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3f33813..f5f26a3 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -72,6 +72,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.WhitelistHelper;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.LocalServices;
@@ -173,10 +174,10 @@
     private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
 
     /**
-     * List of packages that are whitelisted to be trigger augmented autofill.
+     * List of packages/activities that are whitelisted to be trigger augmented autofill.
      */
     @GuardedBy("mLock")
-    private final ArraySet<String> mWhitelistedAugmentAutofillPackages = new ArraySet<>();
+    private final WhitelistHelper mAugmentedWhitelistHelper = new WhitelistHelper();
 
     AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
             LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
@@ -905,13 +906,7 @@
             pw.println(mRemoteAugmentedAutofillServiceInfo);
         }
 
-        final int whitelistSize = mWhitelistedAugmentAutofillPackages.size();
-        pw.print(prefix); pw.print("Packages whitelisted for augmented autofill: ");
-        pw.println(whitelistSize);
-        for (int i = 0; i < whitelistSize; i++) {
-            final String whitelistedPkg = mWhitelistedAugmentAutofillPackages.valueAt(i);
-            pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
-        }
+        mAugmentedWhitelistHelper.dump(prefix, "Augmented autofill whitelist", pw);
 
         pw.print(prefix); pw.print("Field classification enabled: ");
             pw.println(isFieldClassificationEnabledLocked());
@@ -1107,6 +1102,7 @@
                 }
                 mRemoteAugmentedAutofillService.destroy();
                 mRemoteAugmentedAutofillService = null;
+                mRemoteAugmentedAutofillServiceInfo = null;
             }
 
             mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
@@ -1129,9 +1125,8 @@
             Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
                     + activities + ")");
         }
-        whitelistForAugmentedAutofillPackages(packages);
+        whitelistForAugmentedAutofillPackages(packages, activities);
 
-        // TODO(b/123100824): whitelist activities as well
         // TODO(b/122858578): log metrics
         return true;
     }
@@ -1171,28 +1166,29 @@
 
     @GuardedBy("mLock")
     boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
-        // TODO(b/122595322): need to check whitelisted activities as well.
-        final String packageName = componentName.getPackageName();
-        return mWhitelistedAugmentAutofillPackages.contains(packageName);
+        return mAugmentedWhitelistHelper.isWhitelisted(componentName);
     }
 
     @GuardedBy("mLock")
     void setAugmentedAutofillWhitelistLocked(@NonNull AutofillOptions options,
             @NonNull String packageName) {
-        // TODO(b/122595322): need to setwhitelisted activities as well.
-        options.augmentedEnabled = mWhitelistedAugmentAutofillPackages.contains(packageName);
+        options.augmentedAutofillEnabled = mAugmentedWhitelistHelper.isWhitelisted(packageName);
+        options.whitelistedActivitiesForAugmentedAutofill = mAugmentedWhitelistHelper
+                .getWhitelistedComponents(packageName);
     }
 
-    private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
+    /**
+     *
+     * @throws IllegalArgumentException if packages or components are empty.
+     */
+    private void whitelistForAugmentedAutofillPackages(@Nullable List<String> packages,
+            @Nullable List<ComponentName> components) {
         // TODO(b/123100824): add CTS test for when it's null
         synchronized (mLock) {
-            if (packages == null) {
-                if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted augmented packages");
-                mWhitelistedAugmentAutofillPackages.clear();
-            } else {
-                if (mMaster.verbose) Slog.v(TAG, "whitelisting augmented packages: " + packages);
-                mWhitelistedAugmentAutofillPackages.addAll(packages);
+            if (mMaster.verbose) {
+                Slog.v(TAG, "whitelisting packages: " + packages + "and activities: " + components);
             }
+            mAugmentedWhitelistHelper.setWhitelist(packages, components);
             mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
         }
     }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index b33259d..9df09b9 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -20,8 +20,8 @@
 import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
 import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
 import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
+import static android.view.contentcapture.ContentCaptureSession.STATE_NOT_WHITELISTED;
 import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
-import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED;
 
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -29,6 +29,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
@@ -55,6 +56,7 @@
 import android.view.contentcapture.UserDataRemovalRequest;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.WhitelistHelper;
 import com.android.internal.os.IResultReceiver;
 import com.android.server.LocalServices;
 import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
@@ -94,7 +96,7 @@
      * List of packages that are whitelisted to be content captured.
      */
     @GuardedBy("mLock")
-    private final ArraySet<String> mWhitelistedPackages = new ArraySet<>();
+    private final WhitelistHelper mWhitelistHelper = new WhitelistHelper();
 
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
@@ -194,7 +196,7 @@
         final int taskId = activityPresentationInfo.taskId;
         final int displayId = activityPresentationInfo.displayId;
         final ComponentName componentName = activityPresentationInfo.componentName;
-        final boolean whitelisted = isWhitelistedLocked(componentName);
+        final boolean whiteListed = isWhitelistedLocked(componentName);
         final ComponentName serviceComponentName = getServiceComponentName();
         final boolean enabled = isEnabledLocked();
         if (mMaster.mRequestsHistory != null) {
@@ -204,7 +206,7 @@
                     + " t=" + taskId + " d=" + displayId
                     + " s=" + ComponentName.flattenToShortString(serviceComponentName)
                     + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)")
-                    + " w=" + whitelisted;
+                    + " w=" + whiteListed;
             mMaster.mRequestsHistory.log(historyItem);
         }
 
@@ -225,12 +227,12 @@
             return;
         }
 
-        if (!whitelisted) {
+        if (!whiteListed) {
             if (mMaster.debug) {
-                Slog.d(TAG, "startSession(" + componentName + "): not whitelisted");
+                Slog.d(TAG, "startSession(" + componentName + "): package or component "
+                        + "not whitelisted");
             }
-            // TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well
-            setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED,
+            setClientState(clientReceiver, STATE_DISABLED | STATE_NOT_WHITELISTED,
                     /* binder= */ null);
             return;
         }
@@ -270,21 +272,21 @@
 
     @GuardedBy("mLock")
     private boolean isWhitelistedLocked(@NonNull ComponentName componentName) {
-        // TODO(b/122595322): need to check whitelisted activities as well.
-        final String packageName = componentName.getPackageName();
-        return mWhitelistedPackages.contains(packageName);
+        return mWhitelistHelper.isWhitelisted(componentName);
     }
 
-    private void whitelistPackages(@NonNull List<String> packages) {
+    /**
+     * @throws IllegalArgumentException if packages or components are empty.
+     */
+    private void setWhitelist(@Nullable List<String> packages,
+            @Nullable List<ComponentName> components) {
         // TODO(b/122595322): add CTS test for when it's null
         synchronized (mLock) {
-            if (packages == null) {
-                if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages");
-                mWhitelistedPackages.clear();
-            } else {
-                if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages);
-                mWhitelistedPackages.addAll(packages);
+            if (mMaster.verbose) {
+                Slog.v(TAG, "whitelisting packages: " + packages + " and activities: "
+                        + components);
             }
+            mWhitelistHelper.setWhitelist(packages, components);
         }
     }
 
@@ -411,15 +413,15 @@
 
     @GuardedBy("mLock")
     ContentCaptureOptions getOptionsForPackageLocked(@NonNull String packageName) {
-        if (!mWhitelistedPackages.contains(packageName)) {
+        if (!mWhitelistHelper.isWhitelisted(packageName)) {
             if (mMaster.verbose) {
                 Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
             }
             return null;
         }
 
-        // TODO(b/122595322): need to check whitelisted activities as well.
-        final ArraySet<ComponentName> whitelistedComponents = null;
+        final ArraySet<ComponentName> whitelistedComponents = mWhitelistHelper
+                .getWhitelistedComponents(packageName);
         ContentCaptureOptions options = new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel,
                 mMaster.mDevCfgMaxBufferSize, mMaster.mDevCfgIdleFlushingFrequencyMs,
                 mMaster.mDevCfgTextChangeFlushingFrequencyMs, mMaster.mDevCfgLogHistorySize,
@@ -440,12 +442,7 @@
             mRemoteService.dump(prefix2, pw);
         }
 
-        final int whitelistSize = mWhitelistedPackages.size();
-        pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize);
-        for (int i = 0; i < whitelistSize; i++) {
-            final String whitelistedPkg = mWhitelistedPackages.valueAt(i);
-            pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
-        }
+        mWhitelistHelper.dump(prefix, "Whitelist", pw);
 
         if (mSessions.isEmpty()) {
             pw.print(prefix); pw.println("no sessions");
@@ -485,9 +482,8 @@
                 Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
                         + activities + ")");
             }
-            whitelistPackages(packages);
+            setWhitelist(packages, activities);
 
-            // TODO(b/122595322): whitelist activities as well
             // TODO(b/119613670): log metrics
         }
 
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
index a18686d..9b70272 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.contentsuggestions;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -73,6 +74,13 @@
             throw new PackageManager.NameNotFoundException(
                     "Could not get service for " + serviceComponent);
         }
+        if (!Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE.equals(si.permission)) {
+            Slog.w(TAG, "ContentSuggestionsService from '" + si.packageName
+                    + "' does not require permission "
+                    + Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE);
+            throw new SecurityException("Service does not require permission "
+                    + Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE);
+        }
         return si;
     }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d2c39ea..219e046 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1575,8 +1575,7 @@
     public boolean isActiveNetworkMetered() {
         enforceAccessPermission();
 
-        final int uid = Binder.getCallingUid();
-        final NetworkCapabilities caps = getUnfilteredActiveNetworkState(uid).networkCapabilities;
+        final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
         if (caps != null) {
             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         } else {
@@ -3793,10 +3792,10 @@
      * if it's really needed.
      */
     @Override
-    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg) {
         ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
-        mTethering.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+        mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
     }
 
     // Called when we lose the default network and have no replacement yet.
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 18e9906..bbd51ad 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1176,7 +1176,7 @@
 
         @GuardedBy("mLock")
         public boolean isUseableForUserLocked(int userId) {
-            return userId == mCurrentUserId && mUseable;
+            return isCurrentProfileLocked(userId) && mUseable;
         }
 
         @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index b423f62..965b64b 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -55,7 +55,7 @@
     private static final String DEBUG_SYS_LOOPER_STATS_ENABLED =
             "debug.sys.looper_stats_enabled";
     private static final int DEFAULT_SAMPLING_INTERVAL = 1000;
-    private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
+    private static final int DEFAULT_ENTRIES_SIZE_CAP = 1500;
     private static final boolean DEFAULT_ENABLED = true;
     private static final boolean DEFAULT_TRACK_SCREEN_INTERACTIVE = false;
 
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index ec40971..660109c 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.os.Environment;
 import android.os.Handler;
@@ -76,6 +77,7 @@
     private static final String ATTR_VERSION = "version";
     private static final String ATTR_NAME = "name";
     private static final String ATTR_DURATION = "duration";
+    private static final String ATTR_PASSED_HEALTH_CHECK = "passed-health-check";
 
     private static PackageWatchdog sPackageWatchdog;
 
@@ -102,7 +104,7 @@
     // 0 if mPackageCleanup not running.
     private long mDurationAtLastReschedule;
 
-    // TODO(zezeozue): Remove redundant context param
+    // TODO(b/120598832): Remove redundant context param
     private PackageWatchdog(Context context) {
         mContext = context;
         mPolicyFile = new AtomicFile(new File(new File(Environment.getDataDirectory(), "system"),
@@ -161,21 +163,29 @@
      * Starts observing the health of the {@code packages} for {@code observer} and notifies
      * {@code observer} of any package failures within the monitoring duration.
      *
+     * <p>If monitoring a package with {@code withExplicitHealthCheck}, at the end of the monitoring
+     * duration if {@link #onExplicitHealthCheckPassed} was never called,
+     * {@link PackageHealthObserver#execute} will be called as if the package failed.
+     *
      * <p>If {@code observer} is already monitoring a package in {@code packageNames},
-     * the monitoring window of that package will be reset to {@code durationMs}.
+     * the monitoring window of that package will be reset to {@code durationMs} and the health
+     * check state will be reset to a default depending on {@code withExplictHealthCheck}.
      *
      * @throws IllegalArgumentException if {@code packageNames} is empty
      * or {@code durationMs} is less than 1
      */
     public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
-            long durationMs) {
+            long durationMs, boolean withExplicitHealthCheck) {
         if (packageNames.isEmpty() || durationMs < 1) {
             throw new IllegalArgumentException("Observation not started, no packages specified"
                     + "or invalid duration");
         }
         List<MonitoredPackage> packages = new ArrayList<>();
         for (int i = 0; i < packageNames.size(); i++) {
-            packages.add(new MonitoredPackage(packageNames.get(i), durationMs));
+            // When observing packages withExplicitHealthCheck,
+            // MonitoredPackage#mHasExplicitHealthCheckPassed will be false initially.
+            packages.add(new MonitoredPackage(packageNames.get(i), durationMs,
+                            !withExplicitHealthCheck));
         }
         synchronized (mLock) {
             ObserverInternal oldObserver = mAllObservers.get(observer.getName());
@@ -276,7 +286,38 @@
         });
     }
 
-    // TODO(zezeozue): Optimize write? Maybe only write a separate smaller file?
+    /**
+     * Updates the observers monitoring {@code packageName} that explicit health check has passed.
+     *
+     * <p> This update is strictly for registered observers at the time of the call
+     * Observers that register after this signal will have no knowledge of prior signals and will
+     * effectively behave as if the explicit health check hasn't passed for {@code packageName}.
+     *
+     * <p> {@code packageName} can still be considered failed if reported by
+     * {@link #onPackageFailure} before the package expires.
+     *
+     * <p> Triggered by components outside the system server when they are fully functional after an
+     * update.
+     */
+    public void onExplicitHealthCheckPassed(String packageName) {
+        Slog.i(TAG, "Health check passed for package: " + packageName);
+        boolean shouldUpdateFile = false;
+        synchronized (mLock) {
+            for (int observerIdx = 0; observerIdx < mAllObservers.size(); observerIdx++) {
+                ObserverInternal observer = mAllObservers.valueAt(observerIdx);
+                MonitoredPackage monitoredPackage = observer.mPackages.get(packageName);
+                if (monitoredPackage != null && !monitoredPackage.mHasPassedHealthCheck) {
+                    monitoredPackage.mHasPassedHealthCheck = true;
+                    shouldUpdateFile = true;
+                }
+            }
+        }
+        if (shouldUpdateFile) {
+            saveToFileAsync();
+        }
+    }
+
+    // TODO(b/120598832): Optimize write? Maybe only write a separate smaller file?
     // This currently adds about 7ms extra to shutdown thread
     /** Writes the package information to file during shutdown. */
     public void writeNow() {
@@ -322,7 +363,7 @@
          */
         boolean execute(VersionedPackage versionedPackage);
 
-        // TODO(zezeozue): Ensure uniqueness?
+        // TODO(b/120598832): Ensure uniqueness?
         /**
          * Identifier for the observer, should not change across device updates otherwise the
          * watchdog may drop observing packages with the old name.
@@ -393,7 +434,12 @@
             Iterator<ObserverInternal> it = mAllObservers.values().iterator();
             while (it.hasNext()) {
                 ObserverInternal observer = it.next();
-                if (!observer.updateMonitoringDurations(elapsedMs)) {
+                List<MonitoredPackage> failedPackages =
+                        observer.updateMonitoringDurations(elapsedMs);
+                if (!failedPackages.isEmpty()) {
+                    onExplicitHealthCheckFailed(observer, failedPackages);
+                }
+                if (observer.mPackages.isEmpty()) {
                     Slog.i(TAG, "Discarding observer " + observer.mName + ". All packages expired");
                     it.remove();
                 }
@@ -402,6 +448,32 @@
         saveToFileAsync();
     }
 
+    private void onExplicitHealthCheckFailed(ObserverInternal observer,
+            List<MonitoredPackage> failedPackages) {
+        mWorkerHandler.post(() -> {
+            synchronized (mLock) {
+                PackageHealthObserver registeredObserver = observer.mRegisteredObserver;
+                if (registeredObserver != null) {
+                    PackageManager pm = mContext.getPackageManager();
+                    for (int i = 0; i < failedPackages.size(); i++) {
+                        String packageName = failedPackages.get(i).mName;
+                        long versionCode = 0;
+                        try {
+                            versionCode = pm.getPackageInfo(
+                                    packageName, 0 /* flags */).getLongVersionCode();
+                        } catch (PackageManager.NameNotFoundException e) {
+                            Slog.w(TAG, "Explicit health check failed but could not find package "
+                                    + packageName);
+                            // TODO(b/120598832): Skip. We only continue to pass tests for now since
+                            // the tests don't install any packages
+                        }
+                        registeredObserver.execute(new VersionedPackage(packageName, versionCode));
+                    }
+                }
+            }
+        });
+    }
+
     /**
      * Loads mAllObservers from file.
      *
@@ -480,6 +552,7 @@
      */
     static class ObserverInternal {
         public final String mName;
+        //TODO(b/120598832): Add getter for mPackages
         public final ArrayMap<String, MonitoredPackage> mPackages;
         @Nullable
         public PackageHealthObserver mRegisteredObserver;
@@ -505,6 +578,8 @@
                     out.startTag(null, TAG_PACKAGE);
                     out.attribute(null, ATTR_NAME, p.mName);
                     out.attribute(null, ATTR_DURATION, String.valueOf(p.mDurationMs));
+                    out.attribute(null, ATTR_PASSED_HEALTH_CHECK,
+                            String.valueOf(p.mHasPassedHealthCheck));
                     out.endTag(null, TAG_PACKAGE);
                 }
                 out.endTag(null, TAG_OBSERVER);
@@ -529,10 +604,12 @@
          *  {@code elapsedMs}. If any duration is less than 0, the package is removed from
          * observation.
          *
-         * @returns {@code true} if there are still packages to be observed, {@code false} otherwise
+         * @returns a {@link List} of packages that were removed from the observer without explicit
+         * health check passing, or an empty list if no package expired for which an explicit health
+         * check was still pending
          */
-        public boolean updateMonitoringDurations(long elapsedMs) {
-            List<MonitoredPackage> packages = new ArrayList<>();
+        public List<MonitoredPackage> updateMonitoringDurations(long elapsedMs) {
+            List<MonitoredPackage> removedPackages = new ArrayList<>();
             synchronized (mName) {
                 Iterator<MonitoredPackage> it = mPackages.values().iterator();
                 while (it.hasNext()) {
@@ -541,10 +618,13 @@
                     if (newDuration > 0) {
                         p.mDurationMs = newDuration;
                     } else {
+                        if (!p.mHasPassedHealthCheck) {
+                            removedPackages.add(p);
+                        }
                         it.remove();
                     }
                 }
-                return !mPackages.isEmpty();
+                return removedPackages;
             }
         }
 
@@ -574,6 +654,7 @@
             if (TAG_OBSERVER.equals(parser.getName())) {
                 observerName = parser.getAttributeValue(null, ATTR_NAME);
                 if (TextUtils.isEmpty(observerName)) {
+                    Slog.wtf(TAG, "Unable to read observer name");
                     return null;
                 }
             }
@@ -582,17 +663,24 @@
             try {
                 while (XmlUtils.nextElementWithin(parser, innerDepth)) {
                     if (TAG_PACKAGE.equals(parser.getName())) {
-                        String packageName = parser.getAttributeValue(null, ATTR_NAME);
-                        long duration = Long.parseLong(
-                                parser.getAttributeValue(null, ATTR_DURATION));
-                        if (!TextUtils.isEmpty(packageName)) {
-                            packages.add(new MonitoredPackage(packageName, duration));
+                        try {
+                            String packageName = parser.getAttributeValue(null, ATTR_NAME);
+                            long duration = Long.parseLong(
+                                    parser.getAttributeValue(null, ATTR_DURATION));
+                            boolean hasPassedHealthCheck = Boolean.parseBoolean(
+                                    parser.getAttributeValue(null, ATTR_PASSED_HEALTH_CHECK));
+                            if (!TextUtils.isEmpty(packageName)) {
+                                packages.add(new MonitoredPackage(packageName, duration,
+                                        hasPassedHealthCheck));
+                            }
+                        } catch (NumberFormatException e) {
+                            Slog.wtf(TAG, "Skipping package for observer " + observerName, e);
+                            continue;
                         }
                     }
                 }
-            } catch (IOException e) {
-                return null;
-            } catch (XmlPullParserException e) {
+            } catch (XmlPullParserException | IOException e) {
+                Slog.wtf(TAG, "Unable to read observer " + observerName, e);
                 return null;
             }
             if (packages.isEmpty()) {
@@ -605,6 +693,8 @@
     /** Represents a package along with the time it should be monitored for. */
     static class MonitoredPackage {
         public final String mName;
+        // Whether an explicit health check has passed
+        public boolean mHasPassedHealthCheck;
         // System uptime duration to monitor package
         public long mDurationMs;
         // System uptime of first package failure
@@ -612,9 +702,10 @@
         // Number of failures since mUptimeStartMs
         private int mFailures;
 
-        MonitoredPackage(String name, long durationMs) {
+        MonitoredPackage(String name, long durationMs, boolean hasPassedHealthCheck) {
             mName = name;
             mDurationMs = durationMs;
+            mHasPassedHealthCheck = hasPassedHealthCheck;
         }
 
         /**
@@ -626,7 +717,7 @@
             final long now = SystemClock.uptimeMillis();
             final long duration = now - mUptimeStartMs;
             if (duration > TRIGGER_DURATION_MS) {
-                // TODO(zezeozue): Reseting to 1 is not correct
+                // TODO(b/120598832): Reseting to 1 is not correct
                 // because there may be more than 1 failure in the last trigger window from now
                 // This is the RescueParty impl, will leave for now
                 mFailures = 1;
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 18c2722..1fe0271 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -38,9 +38,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.am.SettingsToPropertiesMapper;
 import com.android.server.utils.FlagNamespaceUtils;
 
 import java.io.File;
+import java.util.Arrays;
 
 /**
  * Utilities to help rescue the system from crash loops. Callers are expected to
@@ -129,10 +131,10 @@
     }
 
     /**
-     * Take note of a persistent app crash. If we notice too many of these
+     * Take note of a persistent app or apex module crash. If we notice too many of these
      * events happening in rapid succession, we'll send out a rescue party.
      */
-    public static void notePersistentAppCrash(Context context, int uid) {
+    public static void noteAppCrash(Context context, int uid) {
         if (isDisabled()) return;
         Threshold t = sApps.get(uid);
         if (t == null) {
@@ -158,6 +160,7 @@
      * opportunity to reset any settings depending on our rescue level.
      */
     public static void onSettingsProviderPublished(Context context) {
+        handleNativeRescuePartyResets();
         executeRescueLevel(context);
     }
 
@@ -176,6 +179,13 @@
         return SystemClock.elapsedRealtime();
     }
 
+    private static void handleNativeRescuePartyResets() {
+        if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
+            FlagNamespaceUtils.resetDeviceConfig(Settings.RESET_MODE_TRUSTED_DEFAULTS,
+                    Arrays.asList(SettingsToPropertiesMapper.getResetNativeCategories()));
+        }
+    }
+
     /**
      * Escalate to the next rescue level. After incrementing the level you'll
      * probably want to call {@link #executeRescueLevel(Context)}.
@@ -235,15 +245,15 @@
         Exception res = null;
         final ContentResolver resolver = context.getContentResolver();
         try {
-            Settings.Global.resetToDefaultsAsUser(resolver, null, mode, UserHandle.USER_SYSTEM);
-        } catch (Exception e) {
-            res = new RuntimeException("Failed to reset global settings", e);
-        }
-        try {
             FlagNamespaceUtils.resetDeviceConfig(mode);
         } catch (Exception e) {
             res = new RuntimeException("Failed to reset config settings", e);
         }
+        try {
+            Settings.Global.resetToDefaultsAsUser(resolver, null, mode, UserHandle.USER_SYSTEM);
+        } catch (Exception e) {
+            res = new RuntimeException("Failed to reset global settings", e);
+        }
         for (int userId : getAllUserIds()) {
             try {
                 Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c8e8ef8..e28d484 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1727,7 +1727,8 @@
         final List<AppOpsManager.PackageOps> pkgs = manager.getOpsForPackage(uid, packageName, ops);
         for (AppOpsManager.PackageOps pkg : CollectionUtils.emptyIfNull(pkgs)) {
             for (AppOpsManager.OpEntry op : CollectionUtils.emptyIfNull(pkg.getOps())) {
-                maxTime = Math.max(maxTime, op.getLastAccessTime());
+                maxTime = Math.max(maxTime, op.getLastAccessTime(
+                    AppOpsManager.OP_FLAGS_ALL_TRUSTED));
             }
         }
         return maxTime;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 0955cc5..9fa0053 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -259,7 +259,7 @@
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
                         | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
                         | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
-                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE;
+                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
@@ -819,7 +819,8 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE) != 0) {
+                    if ((events & PhoneStateListener
+                            .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
                         try {
                             r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
                         } catch (RemoteException ex) {
@@ -1550,6 +1551,13 @@
                 log("notifyPreciseCallState: mCallQuality is null, skipping call attributes");
                 notifyCallAttributes = false;
             } else {
+                // If the precise call state is no longer active, reset the call network type and
+                // call quality.
+                if (mPreciseCallState.getForegroundCallState()
+                        != PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
+                    mCallNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+                    mCallQuality = new CallQuality();
+                }
                 mCallAttributes = new CallAttributes(mPreciseCallState, mCallNetworkType,
                         mCallQuality);
             }
@@ -1748,7 +1756,7 @@
 
             for (Record r : mRecords) {
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE)) {
+                        PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) {
                     try {
                         r.callback.onActiveDataSubIdChanged(activeDataSubId);
                     } catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 545baa0..5cca159 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -594,8 +594,9 @@
                 if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
                         > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
                         && !vib.isNotification() && !vib.isRingtone()) {
-                    Slog.e(TAG, "Ignoring incoming vibration as process with uid = "
-                            + uid + " is background");
+                    Slog.e(TAG, "Ignoring incoming vibration as process with"
+                            + " uid = " + uid + " is background,"
+                            + " usage = " + AudioAttributes.usageToString(vib.usageHint));
                     return;
                 }
                 linkVibration(vib);
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 415a892..f9fcef6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -27,6 +27,8 @@
 import android.provider.DeviceConfig.OnPropertyChangedListener;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.text.TextUtils.SimpleStringSplitter;
+import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.Slog;
 
@@ -235,6 +237,8 @@
     // Controlled by Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED
     volatile boolean mFlagBackgroundActivityStartsEnabled;
 
+    volatile ArraySet<String> mPackageNamesWhitelistedForBgActivityStarts = new ArraySet<>();
+
     private final ActivityManagerService mService;
     private ContentResolver mResolver;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -273,6 +277,10 @@
                 Settings.Global.getUriFor(
                         Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED);
 
+    private static final Uri BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI =
+                Settings.Global.getUriFor(
+                        Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);
+
     private final OnPropertyChangedListener mOnDeviceConfigChangedListener =
             new OnPropertyChangedListener() {
                 @Override
@@ -293,9 +301,12 @@
         mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this);
         mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
         mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_ENABLED_URI, false, this);
+        mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI,
+                false, this);
         updateConstants();
         updateActivityStartsLoggingEnabled();
         updateBackgroundActivityStartsEnabled();
+        updateBackgroundActivityStartsPackageNamesWhitelist();
         DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 ActivityThread.currentApplication().getMainExecutor(),
                 mOnDeviceConfigChangedListener);
@@ -325,6 +336,8 @@
             updateActivityStartsLoggingEnabled();
         } else if (BACKGROUND_ACTIVITY_STARTS_ENABLED_URI.equals(uri)) {
             updateBackgroundActivityStartsEnabled();
+        } else if (BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI.equals(uri)) {
+            updateBackgroundActivityStartsPackageNamesWhitelist();
         }
     }
 
@@ -414,6 +427,21 @@
                 Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1) == 1;
     }
 
+    private void updateBackgroundActivityStartsPackageNamesWhitelist() {
+        final String setting = Settings.Global.getString(mResolver,
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);
+        if (TextUtils.isEmpty(setting)) {
+            return;
+        }
+        ArraySet<String> newSet = new ArraySet<>();
+        SimpleStringSplitter splitter = new SimpleStringSplitter(':');
+        splitter.setString(setting);
+        while (splitter.hasNext()) {
+            newSet.add(splitter.next());
+        }
+        mPackageNamesWhitelistedForBgActivityStarts = newSet;
+    }
+
     private void updateMaxCachedProcesses() {
         String maxCachedProcessesFlag = DeviceConfig.getProperty(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MAX_CACHED_PROCESSES);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ccb9d82..73884a0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17623,6 +17623,16 @@
         }
 
         @Override
+        public void killProcess(String processName, int uid, String reason) {
+            synchronized (ActivityManagerService.this) {
+                final ProcessRecord proc = getProcessRecordLocked(processName, uid,
+                        true /* keepIfLarge */);
+                mProcessList.removeProcessLocked(proc, false /* callerWillRestart */,
+                        true /* allowRestart */, reason);
+            }
+        }
+
+        @Override
         public boolean hasRunningActivity(int uid, @Nullable String packageName) {
             if (packageName == null) return false;
 
@@ -17862,6 +17872,10 @@
             return mConstants.mFlagActivityStartsLoggingEnabled;
         }
 
+        public boolean isPackageNameWhitelistedForBgActivityStarts(String packageName) {
+            return mConstants.mPackageNamesWhitelistedForBgActivityStarts.contains(packageName);
+        }
+
         public boolean isBackgroundActivityStartsEnabled() {
             return mConstants.mFlagBackgroundActivityStartsEnabled;
         }
@@ -18475,7 +18489,12 @@
         public int checkPermission(String permName, String pkgName, int userId,
                 TriFunction<String, String, Integer, Integer> superImpl) {
             if (mTargetPackageName.equals(pkgName) && isTargetPermission(permName)) {
-                return superImpl.apply(permName, "com.android.shell", userId);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(permName, "com.android.shell", userId);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
             return superImpl.apply(permName, pkgName, userId);
         }
@@ -18484,7 +18503,12 @@
         public int checkUidPermission(String permName, int uid,
                 BiFunction<String, Integer, Integer> superImpl) {
             if (uid == mTargetUid  && isTargetPermission(permName)) {
-                return superImpl.apply(permName, Process.SHELL_UID);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    return superImpl.apply(permName, Process.SHELL_UID);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
             return superImpl.apply(permName, uid);
         }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index f153ab9..1ff6f4d 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -34,6 +34,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.net.Uri;
 import android.os.Binder;
@@ -406,15 +408,29 @@
         }
 
         if (r != null) {
-            if (r.isPersistent()) {
-                // If a persistent app is stuck in a crash loop, the device isn't very
-                // usable, so we want to consider sending out a rescue party.
-                RescueParty.notePersistentAppCrash(mContext, r.uid);
-            } else {
-                // If a non-persistent app is stuck in crash loop, we want to inform
-                // the package watchdog, maybe an update or experiment can be rolled back.
-                mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
+            boolean isApexModule = false;
+            try {
+                for (String androidPackage : r.getPackageList()) {
+                    ModuleInfo moduleInfo = mContext.getPackageManager().getModuleInfo(
+                            androidPackage, /*flags=*/ 0);
+                    if (moduleInfo != null) {
+                        isApexModule = true;
+                        break;
+                    }
+                }
+            } catch (IllegalStateException | PackageManager.NameNotFoundException e) {
+                // Call to PackageManager#getModuleInfo() can result in NameNotFoundException or
+                // IllegalStateException. In case they are thrown, there isn't much we can do
+                // other than proceed with app crash handling.
             }
+
+            if (r.isPersistent() || isApexModule) {
+                // If a persistent app or apex module is stuck in a crash loop, the device isn't
+                // very usable, so we want to consider sending out a rescue party.
+                RescueParty.noteAppCrash(mContext, r.uid);
+            }
+
+            mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
         }
 
         final int relaunchReason = r != null
diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java
index 0b38ef9..b0b1840 100644
--- a/services/core/java/com/android/server/am/BroadcastDispatcher.java
+++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java
@@ -617,11 +617,9 @@
      * Cancel all current deferrals; that is, make all currently-deferred broadcasts
      * immediately deliverable.  Used by the wait-for-broadcast-idle mechanism.
      */
-    public void cancelDeferrals() {
-        synchronized (mLock) {
-            zeroDeferralTimes(mAlarmBroadcasts);
-            zeroDeferralTimes(mDeferredBroadcasts);
-        }
+    public void cancelDeferralsLocked() {
+        zeroDeferralTimes(mAlarmBroadcasts);
+        zeroDeferralTimes(mDeferredBroadcasts);
     }
 
     private static void zeroDeferralTimes(ArrayList<Deferrals> list) {
diff --git a/services/core/java/com/android/server/am/BroadcastFilter.java b/services/core/java/com/android/server/am/BroadcastFilter.java
index 8e2ca06..34fca23 100644
--- a/services/core/java/com/android/server/am/BroadcastFilter.java
+++ b/services/core/java/com/android/server/am/BroadcastFilter.java
@@ -81,7 +81,9 @@
         StringBuilder sb = new StringBuilder();
         sb.append("BroadcastFilter{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
-        sb.append(" u");
+        sb.append(' ');
+        sb.append(owningUid);
+        sb.append("/u");
         sb.append(owningUserId);
         sb.append(' ');
         sb.append(receiverList);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index efb1c44..70733ef 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -445,7 +445,7 @@
         final long elapsed = finishTime - r.receiverTime;
         r.state = BroadcastRecord.IDLE;
         if (state == BroadcastRecord.IDLE) {
-            Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE");
+            Slog.w(TAG_BROADCAST, "finishReceiver [" + mQueueName + "] called but state is IDLE");
         }
         if (r.allowBackgroundActivityStarts && r.curApp != null) {
             if (elapsed > mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT) {
@@ -478,12 +478,13 @@
         if (!r.timeoutExempt) {
             if (mConstants.SLOW_TIME > 0 && elapsed > mConstants.SLOW_TIME) {
                 if (DEBUG_BROADCAST_DEFERRAL) {
-                    Slog.i(TAG, "Broadcast receiver was slow: " + receiver + " br=" + r);
+                    Slog.i(TAG_BROADCAST, "Broadcast receiver " + (r.nextReceiver - 1)
+                            + " was slow: " + receiver + " br=" + r);
                 }
                 if (r.curApp != null) {
                     mDispatcher.startDeferring(r.curApp.uid);
                 } else {
-                    Slog.d(TAG, "finish receiver curApp is null? " + r);
+                    Slog.d(TAG_BROADCAST, "finish receiver curApp is null? " + r);
                 }
             }
         } else {
@@ -796,9 +797,7 @@
                     skipReceiverLocked(r);
                 }
             } else {
-                if (r.receiverTime == 0) {
-                    r.receiverTime = SystemClock.uptimeMillis();
-                }
+                r.receiverTime = SystemClock.uptimeMillis();
                 maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                         new Intent(r.intent), r.resultCode, r.resultData,
@@ -1083,16 +1082,19 @@
                         if (newCount == 0) {
                             // done!  clear out this record's bookkeeping and deliver
                             if (DEBUG_BROADCAST_DEFERRAL) {
-                                Slog.i(TAG, "Sending broadcast completion for split token "
-                                        + r.splitToken);
+                                Slog.i(TAG_BROADCAST,
+                                        "Sending broadcast completion for split token "
+                                        + r.splitToken + " : " + r.intent.getAction());
                             }
                             mSplitRefcounts.delete(r.splitToken);
                         } else {
                             // still have some split broadcast records in flight; update refcount
                             // and hold off on the callback
                             if (DEBUG_BROADCAST_DEFERRAL) {
-                                Slog.i(TAG, "Result refcount " + newCount + " for split token "
-                                        + r.splitToken + " - not sending completion yet");
+                                Slog.i(TAG_BROADCAST,
+                                        "Result refcount now " + newCount + " for split token "
+                                        + r.splitToken + " : " + r.intent.getAction()
+                                        + " - not sending completion yet");
                             }
                             sendResult = false;
                             mSplitRefcounts.put(r.splitToken, newCount);
@@ -1155,7 +1157,7 @@
                     BroadcastRecord defer;
                     if (r.nextReceiver + 1 == numReceivers) {
                         if (DEBUG_BROADCAST_DEFERRAL) {
-                            Slog.i(TAG, "Sole receiver of " + r
+                            Slog.i(TAG_BROADCAST, "Sole receiver of " + r
                                     + " is under deferral; setting aside and proceeding");
                         }
                         defer = r;
@@ -1185,15 +1187,25 @@
                                 // first split of this record; refcount for 'r' and 'deferred'
                                 r.splitToken = defer.splitToken = nextSplitTokenLocked();
                                 mSplitRefcounts.put(r.splitToken, 2);
+                                if (DEBUG_BROADCAST_DEFERRAL) {
+                                    Slog.i(TAG_BROADCAST,
+                                            "Broadcast needs split refcount; using new token "
+                                            + r.splitToken);
+                                }
                             } else {
                                 // new split from an already-refcounted situation; increment count
                                 final int curCount = mSplitRefcounts.get(token);
                                 if (DEBUG_BROADCAST_DEFERRAL) {
                                     if (curCount == 0) {
-                                        Slog.wtf(TAG, "Split refcount is zero with token for " + r);
+                                        Slog.wtf(TAG_BROADCAST,
+                                                "Split refcount is zero with token for " + r);
                                     }
                                 }
                                 mSplitRefcounts.put(token, curCount + 1);
+                                if (DEBUG_BROADCAST_DEFERRAL) {
+                                    Slog.i(TAG_BROADCAST, "New split count for token " + token
+                                            + " is " + (curCount + 1));
+                                }
                             }
                         }
                     }
@@ -1529,7 +1541,7 @@
         if (skip) {
             if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                     "Skipping delivery of ordered [" + mQueueName + "] "
-                    + r + " for whatever reason");
+                    + r + " for reason described above");
             r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
             r.receiver = null;
             r.curFilter = null;
@@ -1858,7 +1870,10 @@
     // Used by wait-for-broadcast-idle : fast-forward all current deferrals to
     // be immediately deliverable.
     void cancelDeferrals() {
-        mDispatcher.cancelDeferrals();
+        synchronized (mService) {
+            mDispatcher.cancelDeferralsLocked();
+            scheduleBroadcastsLocked();
+        }
     }
 
     String describeState() {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index fa9b79d..1352504 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -332,7 +332,6 @@
                 }
                 splitReceivers.add(o);
                 receivers.remove(i);
-                break;
             } else {
                 i++;
             }
@@ -350,6 +349,7 @@
                 resultData, resultExtras, ordered, sticky, initialSticky, userId,
                 allowBackgroundActivityStarts, timeoutExempt);
 
+        split.splitToken = this.splitToken;
         return split;
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 399b818..02d31b8 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -249,6 +249,10 @@
     // Threshold of number of cached+empty where we consider memory critical.
     static final int TRIM_LOW_THRESHOLD = 5;
 
+    // If true, then we pass the flag to ART to load the app image startup cache.
+    private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE =
+            "persist.device_config.runtime_native.use_app_image_startup_cache";
+
     // Low Memory Killer Daemon command codes.
     // These must be kept in sync with the definitions in lmkd.c
     //
@@ -1559,6 +1563,13 @@
                 runtimeFlags |= policyBits;
             }
 
+            String useAppImageCache = SystemProperties.get(
+                    PROPERTY_USE_APP_IMAGE_STARTUP_CACHE, "");
+            // Property defaults to true currently.
+            if (!TextUtils.isEmpty(useAppImageCache) && !useAppImageCache.equals("false")) {
+                runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
+            }
+
             String invokeWith = null;
             if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                 // Debuggable apps may include a wrapper script with their library directory.
@@ -2852,6 +2863,15 @@
                     pos--;
                 }
                 mLruProcesses.add(pos, app);
+                if (pos == mLruProcessActivityStart) {
+                    mLruProcessActivityStart++;
+                }
+                if (pos == mLruProcessServiceStart) {
+                    // Unless {@code #hasService} is implemented, currently the starting position
+                    // for activity and service are the same, so the incoming position may equal to
+                    // the starting position of service.
+                    mLruProcessServiceStart++;
+                }
                 // If this process is part of a group, need to pull up any other processes
                 // in that group to be with it.
                 int endIndex = pos - 1;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index fcc857b..51b1ae1 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -55,6 +55,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.procstats.ProcessState;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.os.BatteryStatsImpl;
@@ -73,7 +74,7 @@
  * Full information about a particular process that
  * is currently running.
  */
-final class ProcessRecord implements WindowProcessListener {
+class ProcessRecord implements WindowProcessListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;
 
     private final ActivityManagerService mService; // where we came from
@@ -1303,6 +1304,27 @@
             ServerProtoEnums.DATA_APP;
     }
 
+    /**
+     * Unless configured otherwise, swallow ANRs in background processes & kill the process.
+     * Non-private access is for tests only.
+     */
+    @VisibleForTesting
+    boolean isSilentAnr() {
+        return !getShowBackground() && !isInterestingForBackgroundTraces();
+    }
+
+    /** Non-private access is for tests only. */
+    @VisibleForTesting
+    List<ProcessRecord> getLruProcessList() {
+        return mService.mProcessList.mLruProcesses;
+    }
+
+    /** Non-private access is for tests only. */
+    @VisibleForTesting
+    boolean isMonitorCpuUsage() {
+        return mService.MONITOR_CPU_USAGE;
+    }
+
     void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
             String parentShortComponentName, WindowProcessController parentProcess,
             boolean aboveSystem, String annotation) {
@@ -1312,16 +1334,10 @@
         mWindowProcessController.appEarlyNotResponding(annotation, () -> kill("anr", true));
 
         long anrTime = SystemClock.uptimeMillis();
-        if (ActivityManagerService.MONITOR_CPU_USAGE) {
+        if (isMonitorCpuUsage()) {
             mService.updateCpuStatsNow();
         }
 
-        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
-        boolean showBackground = Settings.Secure.getInt(mService.mContext.getContentResolver(),
-                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-
-        boolean isSilentANR;
-
         synchronized (mService) {
             // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
             if (mService.mAtmInternal.isShuttingDown()) {
@@ -1353,8 +1369,7 @@
             firstPids.add(pid);
 
             // Don't dump other PIDs if it's a background ANR
-            isSilentANR = !showBackground && !isInterestingForBackgroundTraces();
-            if (!isSilentANR) {
+            if (!isSilentAnr()) {
                 int parentPid = pid;
                 if (parentProcess != null && parentProcess.getPid() > 0) {
                     parentPid = parentProcess.getPid();
@@ -1363,8 +1378,8 @@
 
                 if (MY_PID != pid && MY_PID != parentPid) firstPids.add(MY_PID);
 
-                for (int i = mService.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
-                    ProcessRecord r = mService.mProcessList.mLruProcesses.get(i);
+                for (int i = getLruProcessList().size() - 1; i >= 0; i--) {
+                    ProcessRecord r = getLruProcessList().get(i);
                     if (r != null && r.thread != null) {
                         int myPid = r.pid;
                         if (myPid > 0 && myPid != pid && myPid != parentPid && myPid != MY_PID) {
@@ -1405,7 +1420,7 @@
 
         // don't dump native PIDs for background ANRs unless it is the process of interest
         String[] nativeProcs = null;
-        if (isSilentANR) {
+        if (isSilentAnr()) {
             for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
                 if (NATIVE_STACKS_OF_INTEREST[i].equals(processName)) {
                     nativeProcs = new String[] { processName };
@@ -1429,11 +1444,11 @@
         // For background ANRs, don't pass the ProcessCpuTracker to
         // avoid spending 1/2 second collecting stats to rank lastPids.
         File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
-                (isSilentANR) ? null : processCpuTracker, (isSilentANR) ? null : lastPids,
+                (isSilentAnr()) ? null : processCpuTracker, (isSilentAnr()) ? null : lastPids,
                 nativePids);
 
         String cpuInfo = null;
-        if (ActivityManagerService.MONITOR_CPU_USAGE) {
+        if (isMonitorCpuUsage()) {
             mService.updateCpuStatsNow();
             synchronized (mService.mProcessCpuTracker) {
                 cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
@@ -1477,9 +1492,13 @@
         }
 
         synchronized (mService) {
-            mService.mBatteryStatsService.noteProcessAnr(processName, uid);
+            // mBatteryStatsService can be null if the AMS is constructed with injector only. This
+            // will only happen in tests.
+            if (mService.mBatteryStatsService != null) {
+                mService.mBatteryStatsService.noteProcessAnr(processName, uid);
+            }
 
-            if (isSilentANR) {
+            if (isSilentAnr()) {
                 kill("bg anr", true);
                 return;
             }
@@ -1488,20 +1507,28 @@
             makeAppNotRespondingLocked(activityShortComponentName,
                     annotation != null ? "ANR " + annotation : "ANR", info.toString());
 
-            // Bring up the infamous App Not Responding dialog
-            Message msg = Message.obtain();
-            msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
-            msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
+            // mUiHandler can be null if the AMS is constructed with injector only. This will only
+            // happen in tests.
+            if (mService.mUiHandler != null) {
+                // Bring up the infamous App Not Responding dialog
+                Message msg = Message.obtain();
+                msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
+                msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
 
-            mService.mUiHandler.sendMessage(msg);
+                mService.mUiHandler.sendMessage(msg);
+            }
         }
     }
 
     private void makeAppNotRespondingLocked(String activity, String shortMsg, String longMsg) {
         setNotResponding(true);
-        notRespondingReport = mService.mAppErrors.generateProcessError(this,
-                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
-                activity, shortMsg, longMsg, null);
+        // mAppErrors can be null if the AMS is constructed with injector only. This will only
+        // happen in tests.
+        if (mService.mAppErrors != null) {
+            notRespondingReport = mService.mAppErrors.generateProcessError(this,
+                    ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
+                    activity, shortMsg, longMsg, null);
+        }
         startAppProblemLocked();
         getWindowProcessController().stopFreezingActivities();
     }
@@ -1539,4 +1566,9 @@
                 (info != null && "com.android.systemui".equals(info.packageName))
                 || (hasTopUi() || hasOverlayUi());
     }
+
+    private boolean getShowBackground() {
+        return Settings.Secure.getInt(mService.mContext.getContentResolver(),
+                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 894a704..194549f 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.annotation.NonNull;
 import android.content.ContentResolver;
 import android.database.ContentObserver;
 import android.net.Uri;
@@ -78,11 +79,11 @@
     // permission in the corresponding .te file your feature belongs to.
     @VisibleForTesting
     static final String[] sDeviceConfigScopes = new String[] {
-        DeviceConfig.ActivityManagerNativeBoot.NAMESPACE,
-        DeviceConfig.MediaNative.NAMESPACE,
+        DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
+        DeviceConfig.NAMESPACE_MEDIA_NATIVE,
         DeviceConfig.NAMESPACE_NETD_NATIVE,
-        DeviceConfig.RuntimeNativeBoot.NAMESPACE,
+        DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
         DeviceConfig.RuntimeNative.NAMESPACE,
     };
 
@@ -167,7 +168,7 @@
      * booting.
      * @return
      */
-    public static String[] getResetNativeCategories() {
+    public static @NonNull String[] getResetNativeCategories() {
         if (!isNativeFlagsResetPerformed()) {
             return new String[0];
         }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 70c28a8..ba7288e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -16,6 +16,9 @@
 
 package com.android.server.appop;
 
+import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
+import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
+import static android.app.AppOpsManager.OP_FLAGS_ALL;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.app.AppOpsManager.OP_PLAY_AUDIO;
 import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
@@ -23,12 +26,12 @@
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION;
-import static android.app.AppOpsManager.UID_STATE_LAST_NON_RESTRICTED;
+import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
 import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
 import static android.app.AppOpsManager.UID_STATE_TOP;
-import static android.app.AppOpsManager._NUM_UID_STATE;
 import static android.app.AppOpsManager.modeToName;
 import static android.app.AppOpsManager.opToName;
+import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -39,6 +42,9 @@
 import android.app.AppOpsManager;
 import android.app.AppOpsManager.HistoricalOps;
 import android.app.AppOpsManager.HistoricalOpsRequest;
+import android.app.AppOpsManager.Mode;
+import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFlags;
 import android.app.AppOpsManagerInternal;
 import android.app.AppOpsManagerInternal.CheckOpsDelegate;
 import android.content.BroadcastReceiver;
@@ -76,6 +82,8 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.KeyValueListParser;
+import android.util.LongSparseArray;
+import android.util.LongSparseLongArray;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -164,36 +172,6 @@
         UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_NONEXISTENT
     };
 
-    static final String[] UID_STATE_NAMES = new String[] {
-            "pers ",    // UID_STATE_PERSISTENT
-            "top  ",    // UID_STATE_TOP
-            "fgsvcl",   // UID_STATE_FOREGROUND_SERVICE_LOCATION
-            "fgsvc",    // UID_STATE_FOREGROUND_SERVICE
-            "fg   ",    // UID_STATE_FOREGROUND
-            "bg   ",    // UID_STATE_BACKGROUND
-            "cch  ",    // UID_STATE_CACHED
-    };
-
-    static final String[] UID_STATE_TIME_ATTRS = new String[] {
-            "tp",       // UID_STATE_PERSISTENT
-            "tt",       // UID_STATE_TOP
-            "tfsl",     // UID_STATE_FOREGROUND_SERVICE_LOCATION
-            "tfs",      // UID_STATE_FOREGROUND_SERVICE
-            "tf",       // UID_STATE_FOREGROUND
-            "tb",       // UID_STATE_BACKGROUND
-            "tc",       // UID_STATE_CACHED
-    };
-
-    static final String[] UID_STATE_REJECT_ATTRS = new String[] {
-            "rp",       // UID_STATE_PERSISTENT
-            "rt",       // UID_STATE_TOP
-            "rfsl",     // UID_STATE_FOREGROUND_SERVICE_LOCATION
-            "rfs",      // UID_STATE_FOREGROUND_SERVICE
-            "rf",       // UID_STATE_FOREGROUND
-            "rb",       // UID_STATE_BACKGROUND
-            "rc",       // UID_STATE_CACHED
-    };
-
     Context mContext;
     final AtomicFile mFile;
     final Handler mHandler;
@@ -355,12 +333,14 @@
 
         public boolean isDefault() {
             return (pkgOps == null || pkgOps.isEmpty())
-                    && (opModes == null || opModes.size() <= 0);
+                    && (opModes == null || opModes.size() <= 0)
+                    && (state == UID_STATE_CACHED
+                    && (pendingState == UID_STATE_CACHED));
         }
 
-        int evalMode(int mode) {
+        int evalMode(int op, int mode) {
             if (mode == AppOpsManager.MODE_FOREGROUND) {
-                return state <= UID_STATE_LAST_NON_RESTRICTED
+                return state <= AppOpsManager.resolveLastRestrictedUidState(op)
                         ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
             }
             return mode;
@@ -425,41 +405,121 @@
     }
 
     final static class Op {
+        int op;
+        boolean running;
         final UidState uidState;
-        final int uid;
-        final String packageName;
-        final int op;
-        int proxyUid = -1;
-        String proxyPackageName;
-        int mode;
-        int duration;
-        long time[] = new long[_NUM_UID_STATE];
-        long rejectTime[] = new long[_NUM_UID_STATE];
+        final @NonNull String packageName;
+
+        private @Mode int mode;
+        private @Nullable LongSparseLongArray mAccessTimes;
+        private @Nullable LongSparseLongArray mRejectTimes;
+        private @Nullable LongSparseLongArray mDurations;
+        private @Nullable LongSparseLongArray mProxyUids;
+        private @Nullable LongSparseArray<String> mProxyPackageNames;
+
         int startNesting;
         long startRealtime;
 
-        Op(UidState _uidState, String _packageName, int _op) {
-            uidState = _uidState;
-            uid = _uidState.uid;
-            packageName = _packageName;
-            op = _op;
-            mode = AppOpsManager.opToDefaultMode(op);
-        }
-
-        boolean hasAnyTime() {
-            for (int i = 0; i < AppOpsManager._NUM_UID_STATE; i++) {
-                if (time[i] != 0) {
-                    return true;
-                }
-                if (rejectTime[i] != 0) {
-                    return true;
-                }
-            }
-            return false;
+        Op(UidState uidState, String packageName, int op) {
+            this.op = op;
+            this.uidState = uidState;
+            this.packageName = packageName;
+            this.mode = AppOpsManager.opToDefaultMode(op);
         }
 
         int getMode() {
-            return uidState.evalMode(mode);
+            return mode;
+        }
+
+        int evalMode() {
+            return uidState.evalMode(op, mode);
+        }
+
+        /** @hide */
+        public void accessed(long time, int proxyUid, @Nullable String proxyPackageName,
+            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        /** @hide */
+        public void rejected(long time, int proxyUid, @Nullable String proxyPackageName,
+            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mRejectTimes == null) {
+                mRejectTimes = new LongSparseLongArray();
+            }
+            mRejectTimes.put(key, time);
+            updateProxyState(key, proxyUid, proxyPackageName);
+            if (mDurations != null) {
+                mDurations.delete(key);
+            }
+        }
+
+        /** @hide */
+        public void started(long time, @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, -1 /*duration*/, uidState, flags);
+            running = true;
+        }
+
+        /** @hide */
+        public void finished(long time, long duration, @AppOpsManager.UidState int uidState,
+            @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+            running = false;
+        }
+
+        /** @hide */
+        public void running(long time, long duration, @AppOpsManager.UidState int uidState,
+            @OpFlags int flags) {
+            updateAccessTimeAndDuration(time, duration, uidState, flags);
+        }
+
+        /** @hide */
+        public void continuing(long duration, @AppOpsManager.UidState int uidState,
+            @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateAccessTimeAndDuration(long time, long duration,
+            @AppOpsManager.UidState int uidState, @OpFlags int flags) {
+            final long key = AppOpsManager.makeKey(uidState, flags);
+            if (mAccessTimes == null) {
+                mAccessTimes = new LongSparseLongArray();
+            }
+            mAccessTimes.put(key, time);
+            if (mDurations == null) {
+                mDurations = new LongSparseLongArray();
+            }
+            mDurations.put(key, duration);
+        }
+
+        private void updateProxyState(long key, int proxyUid,
+            @Nullable String proxyPackageName) {
+            if (mProxyUids == null) {
+                mProxyUids = new LongSparseLongArray();
+            }
+            mProxyUids.put(key, proxyUid);
+            if (mProxyPackageNames == null) {
+                mProxyPackageNames = new LongSparseArray<>();
+            }
+            mProxyPackageNames.put(key, proxyPackageName);
+        }
+
+        boolean hasAnyTime() {
+            return (mAccessTimes != null && mAccessTimes.size() > 0)
+                || (mRejectTimes != null && mRejectTimes.size() > 0);
         }
     }
 
@@ -812,7 +872,7 @@
                 final int opCount = client.mStartedOps.size();
                 for (int j = opCount - 1; j >= 0; j--) {
                     final Op op = client.mStartedOps.get(j);
-                    if (uid == op.uid && packageName.equals(op.packageName)) {
+                    if (uid == op.uidState.uid && packageName.equals(op.packageName)) {
                         finishOperationLocked(op, /*finishNested*/ true);
                         client.mStartedOps.remove(j);
                         if (op.startNesting <= 0) {
@@ -829,9 +889,9 @@
                 final int opCount = ops.size();
                 for (int i = 0; i < opCount; i++) {
                     final Op op = ops.valueAt(i);
-                    if (op.duration == -1) {
+                    if (op.running) {
                         scheduleOpActiveChangedIfNeededLocked(
-                                op.op, op.uid, op.packageName, false);
+                                op.op, op.uidState.uid, op.packageName, false);
                     }
                 }
             }
@@ -854,7 +914,7 @@
             if (uidState != null && uidState.pendingState != newState) {
                 final int oldPendingState = uidState.pendingState;
                 uidState.pendingState = newState;
-                if (newState < uidState.state || newState <= UID_STATE_LAST_NON_RESTRICTED) {
+                if (newState < uidState.state || newState <= UID_STATE_MAX_LAST_NON_RESTRICTED) {
                     // We are moving to a more important state, or the new state is in the
                     // foreground, then always do it immediately.
                     commitUidPendingStateLocked(uidState);
@@ -880,8 +940,18 @@
                         for (int j = ops.size() - 1; j >= 0; j--) {
                             final Op op = ops.valueAt(j);
                             if (op.startNesting > 0) {
-                                op.time[oldPendingState] = now;
-                                op.time[newState] = now;
+                                final long duration = SystemClock.elapsedRealtime()
+                                        - op.startRealtime;
+                                // We don't support proxy long running ops (start/stop)
+                                mHistoricalRegistry.increaseOpAccessDuration(op.op,
+                                        op.uidState.uid, op.packageName, oldPendingState,
+                                        AppOpsManager.OP_FLAG_SELF, duration);
+                                // Finish the op in the old state
+                                op.finished(now, duration, oldPendingState,
+                                        AppOpsManager.OP_FLAG_SELF);
+                                // Start the op in the new state
+                                op.startRealtime = now;
+                                op.started(now, newState, AppOpsManager.OP_FLAG_SELF);
                             }
                         }
                     }
@@ -911,13 +981,7 @@
             resOps = new ArrayList<>();
             for (int j=0; j<pkgOps.size(); j++) {
                 Op curOp = pkgOps.valueAt(j);
-                final boolean running = curOp.duration == -1;
-                long duration = running
-                        ? (elapsedNow - curOp.startRealtime)
-                        : curOp.duration;
-                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                        curOp.rejectTime, (int) duration, running, curOp.proxyUid,
-                        curOp.proxyPackageName));
+                resOps.add(getOpEntryForResult(curOp, elapsedNow));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
@@ -926,13 +990,7 @@
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    final boolean running = curOp.duration == -1;
-                    final long duration = running
-                            ? (elapsedNow - curOp.startRealtime)
-                            : curOp.duration;
-                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                            curOp.rejectTime, (int) duration, running, curOp.proxyUid,
-                            curOp.proxyPackageName));
+                    resOps.add(getOpEntryForResult(curOp, elapsedNow));
                 }
             }
         }
@@ -947,8 +1005,7 @@
         if (ops == null) {
             resOps = new ArrayList<>();
             for (int j=0; j<uidOps.size(); j++) {
-                resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(j), uidOps.valueAt(j),
-                        0, 0, 0, -1, null));
+                resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
             }
         } else {
             for (int j=0; j<ops.length; j++) {
@@ -957,14 +1014,27 @@
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(index), uidOps.valueAt(index),
-                            0, 0, 0, -1, null));
+                    resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
                 }
             }
         }
         return resOps;
     }
 
+    private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
+        if (op.running) {
+            op.continuing(elapsedNow - op.startRealtime,
+                op.uidState.state, AppOpsManager.OP_FLAG_SELF);
+        }
+        final OpEntry entry = new OpEntry(op.op, op.running, op.mode,
+            op.mAccessTimes != null ? op.mAccessTimes.clone() : null,
+            op.mRejectTimes != null ? op.mRejectTimes.clone() : null,
+            op.mDurations != null ? op.mDurations.clone() : null,
+            op.mProxyUids != null ? op.mProxyUids.clone() : null,
+            op.mProxyPackageNames != null ? op.mProxyPackageNames.clone() : null);
+        return entry;
+    }
+
     @Override
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
@@ -1026,13 +1096,14 @@
     @Override
     public void getHistoricalOps(int uid, @NonNull String packageName,
             @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
-            @NonNull RemoteCallback callback) {
+            @OpFlags int flags, @NonNull RemoteCallback callback) {
         // Use the builder to validate arguments.
-        final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
+        new HistoricalOpsRequest.Builder(
                 beginTimeMillis, endTimeMillis)
                 .setUid(uid)
                 .setPackageName(packageName)
                 .setOpNames(opNames)
+                .setFlags(flags)
                 .build();
         Preconditions.checkNotNull(callback, "callback cannot be null");
 
@@ -1041,79 +1112,23 @@
 
         final String[] opNamesArray = (opNames != null)
                 ? opNames.toArray(new String[opNames.size()]) : null;
-        if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) {
-            // TODO (bug:122218838): Remove once the feature fully enabled.
-            getHistoricalPackagesOpsCompat(uid, packageName, opNamesArray, beginTimeMillis,
-                    endTimeMillis, callback);
-        } else {
-            // Must not hold the appops lock
-            mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
-                    beginTimeMillis, endTimeMillis, callback);
-        }
-    }
 
-    private void getHistoricalPackagesOpsCompat(int uid, @NonNull String packageName,
-            @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
-            @NonNull RemoteCallback callback) {
-        synchronized (AppOpsService.this) {
-            final HistoricalOps ops = new HistoricalOps(beginTimeMillis, endTimeMillis);
-            if (opNames == null) {
-                opNames = AppOpsManager.getOpStrs();
-            }
-            final int uidStateCount = mUidStates.size();
-            for (int uidIdx = 0; uidIdx < uidStateCount; uidIdx++) {
-                final UidState uidState = mUidStates.valueAt(uidIdx);
-                if (uidState.pkgOps == null || uidState.pkgOps.isEmpty()
-                        || (uid != Process.INVALID_UID && uid != uidState.uid)) {
-                    continue;
-                }
-                final ArrayMap<String, Ops> packages = uidState.pkgOps;
-                final int packageCount = packages.size();
-                for (int pkgIdx = 0; pkgIdx < packageCount; pkgIdx++) {
-                    final Ops pkgOps = packages.valueAt(pkgIdx);
-                    if (packageName != null && !packageName.equals(pkgOps.packageName)) {
-                        continue;
-                    }
-                    final int opCount = opNames.length;
-                    for (int opIdx = 0; opIdx < opCount; opIdx++) {
-                        final String opName = opNames[opIdx];
-                        if (!ArrayUtils.contains(opNames, opName)) {
-                            continue;
-                        }
-                        final int opCode = AppOpsManager.strOpToOp(opName);
-                        final Op op = pkgOps.get(opCode);
-                        if (op == null) {
-                            continue;
-                        }
-                        final int stateCount = AppOpsManager._NUM_UID_STATE;
-                        for (int stateIdx = 0; stateIdx < stateCount; stateIdx++) {
-                            if (op.rejectTime[stateIdx] != 0) {
-                                ops.increaseRejectCount(opCode, uidState.uid,
-                                        pkgOps.packageName, stateIdx, 1);
-                            } else if (op.time[stateIdx] != 0) {
-                                ops.increaseAccessCount(opCode, uidState.uid,
-                                        pkgOps.packageName, stateIdx, 1);
-                            }
-                        }
-                    }
-                }
-            }
-            final Bundle payload = new Bundle();
-            payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, ops);
-            callback.sendResult(payload);
-        }
+        // Must not hold the appops lock
+        mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
+                beginTimeMillis, endTimeMillis, flags, callback);
     }
 
     @Override
     public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
             @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
-            @NonNull RemoteCallback callback) {
+            @OpFlags int flags, @NonNull RemoteCallback callback) {
         // Use the builder to validate arguments.
-        final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
+        new HistoricalOpsRequest.Builder(
                 beginTimeMillis, endTimeMillis)
                 .setUid(uid)
                 .setPackageName(packageName)
                 .setOpNames(opNames)
+                .setFlags(flags)
                 .build();
         Preconditions.checkNotNull(callback, "callback cannot be null");
 
@@ -1125,7 +1140,7 @@
 
         // Must not hold the appops lock
         mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
-                beginTimeMillis, endTimeMillis, callback);
+                beginTimeMillis, endTimeMillis, flags, callback);
     }
 
     @Override
@@ -1172,7 +1187,7 @@
         }
     }
 
-    void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
+    private void enforceManageAppOpsModes(int callingPid, int callingUid, int targetUid) {
         if (callingPid == Process.myPid()) {
             return;
         }
@@ -1316,6 +1331,8 @@
                 return;
             }
 
+            boolean scheduleWrite = false;
+
             int numPkgs = pkgOps.size();
             for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
                 Ops ops = pkgOps.valueAt(pkgNum);
@@ -1327,14 +1344,14 @@
 
                 int defaultMode = AppOpsManager.opToDefaultMode(code);
                 if (op.mode != defaultMode) {
-                    Slog.w(TAG, "resetting app-op mode for " + AppOpsManager.opToName(code) + " of "
-                            + pkgOps.keyAt(pkgNum));
-
                     op.mode = defaultMode;
-
-                    scheduleWriteLocked();
+                    scheduleWrite = true;
                 }
             }
+
+            if (scheduleWrite) {
+                scheduleWriteLocked();
+            }
         }
     }
 
@@ -1544,9 +1561,10 @@
                             curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
                             changed = true;
                             uidChanged = true;
-                            callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
+                            final int uid = curOp.uidState.uid;
+                            callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
                                     mOpModeWatchers.get(curOp.op));
-                            callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
+                            callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
                                     mPackageModeWatchers.get(packageName));
                             if (!curOp.hasAnyTime()) {
                                 pkgOps.removeAt(j);
@@ -1727,6 +1745,7 @@
     private int checkOperationUnchecked(int code, int uid, String packageName,
                 boolean raw) {
         synchronized (this) {
+            checkPackage(uid, packageName);
             if (isOpRestrictedLocked(uid, code, packageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
@@ -1735,13 +1754,13 @@
             if (uidState != null && uidState.opModes != null
                     && uidState.opModes.indexOfKey(code) >= 0) {
                 final int rawMode = uidState.opModes.get(code);
-                return raw ? rawMode : uidState.evalMode(rawMode);
+                return raw ? rawMode : uidState.evalMode(code, rawMode);
             }
             Op op = getOpLocked(code, uid, packageName, false, true, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
-            return op.mode;
+            return raw ? op.mode : op.evalMode();
         }
     }
 
@@ -1855,21 +1874,32 @@
             String proxyPackageName, int proxiedUid, String proxiedPackageName) {
         verifyIncomingUid(proxyUid);
         verifyIncomingOp(code);
+
         String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
         if (resolveProxyPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
+
+        final boolean isProxyTrusted = mContext.checkPermission(
+                Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
+                == PackageManager.PERMISSION_GRANTED;
+
+        final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
+                : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
         final int proxyMode = noteOperationUnchecked(code, proxyUid,
-                resolveProxyPackageName, -1, null);
+                resolveProxyPackageName, Process.INVALID_UID, null, proxyFlags);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
+
         String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
         if (resolveProxiedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
+        final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
+                : AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
-                proxyMode, resolveProxyPackageName);
+                proxyUid, resolveProxyPackageName, proxiedFlags);
     }
 
     @Override
@@ -1892,11 +1922,12 @@
         if (resolvedPackageName == null) {
             return AppOpsManager.MODE_IGNORED;
         }
-        return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
+        return noteOperationUnchecked(code, uid, resolvedPackageName, Process.INVALID_UID, null,
+                AppOpsManager.OP_FLAG_SELF);
     }
 
     private int noteOperationUnchecked(int code, int uid, String packageName,
-            int proxyUid, String proxyPackageName) {
+            int proxyUid, String proxyPackageName, @OpFlags int flags) {
         synchronized (this) {
             final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
                     false /* uidMismatchExpected */);
@@ -1914,49 +1945,52 @@
                 return AppOpsManager.MODE_IGNORED;
             }
             final UidState uidState = ops.uidState;
-            if (op.duration == -1) {
+            if (op.running) {
+                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
+                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
-                        + " code " + code + " time=" + op.time[uidState.state]
-                        + " duration=" + op.duration);
+                        + " code " + code + " time=" + entry.getLastAccessTime(uidState.state,
+                        uidState.state, flags) + " duration=" + entry.getLastDuration(
+                                uidState.state, uidState.state, flags));
             }
-            op.duration = 0;
+
             final int switchCode = AppOpsManager.opToSwitch(code);
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode));
+                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejectTime[uidState.state] = System.currentTimeMillis();
+                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            uidState.state, flags);
+                    mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
+                            uidState.state, flags);
                     scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
-                    mHistoricalRegistry.incrementOpRejected(op.op, uid, packageName,
-                            uidState.state);
                     return uidMode;
                 }
             } else {
                 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
-                final int mode = switchOp.getMode();
-                if (mode != AppOpsManager.MODE_ALLOWED) {
+                final int mode = switchOp.evalMode();
+                if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejectTime[uidState.state] = System.currentTimeMillis();
-                    scheduleOpNotedIfNeededLocked(op.op, uid, packageName, mode);
-                    mHistoricalRegistry.incrementOpRejected(op.op, uid, packageName,
-                            uidState.state);
+                    op.rejected(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                            uidState.state, flags);
+                    mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
+                            uidState.state, flags);
+                    scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
                     return mode;
                 }
             }
             if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
-            op.time[uidState.state] = System.currentTimeMillis();
+            op.accessed(System.currentTimeMillis(), proxyUid, proxyPackageName,
+                    uidState.state, flags);
             mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
-                    uidState.state);
-            op.rejectTime[uidState.state] = 0;
-            op.proxyUid = proxyUid;
-            op.proxyPackageName = proxyPackageName;
+                    uidState.state, flags);
             scheduleOpNotedIfNeededLocked(code, uid, packageName,
                     AppOpsManager.MODE_ALLOWED);
             return AppOpsManager.MODE_ALLOWED;
@@ -2080,29 +2114,34 @@
             final UidState uidState = ops.uidState;
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
+            final int opCode = op.op;
             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode));
+                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED
                         && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
-                    op.rejectTime[uidState.state] = System.currentTimeMillis();
-                    mHistoricalRegistry.incrementOpRejected(op.op, uid, packageName,
-                            uidState.state);
+                    // We don't support proxy long running ops (start/stop)
+                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
+                            uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return uidMode;
                 }
             } else {
                 final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
-                final int mode = switchOp.getMode();
+                final int mode = switchOp.evalMode();
                 if (mode != AppOpsManager.MODE_ALLOWED
                         && (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
                     if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
-                    op.rejectTime[uidState.state] = System.currentTimeMillis();
-                    mHistoricalRegistry.incrementOpRejected(op.op, uid, packageName,
-                            uidState.state);
+                    // We don't support proxy long running ops (start/stop)
+                    op.rejected(System.currentTimeMillis(), -1 /*proxyUid*/,
+                            null /*proxyPackage*/, uidState.state, AppOpsManager.OP_FLAG_SELF);
+                    mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
+                            uidState.state, AppOpsManager.OP_FLAG_SELF);
                     return mode;
                 }
             }
@@ -2110,11 +2149,12 @@
                     + " package " + resolvedPackageName);
             if (op.startNesting == 0) {
                 op.startRealtime = SystemClock.elapsedRealtime();
-                op.time[uidState.state] = System.currentTimeMillis();
-                mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
-                        uidState.state);
-                op.rejectTime[uidState.state] = 0;
-                op.duration = -1;
+                // We don't support proxy long running ops (start/stop)
+                op.started(System.currentTimeMillis(), uidState.state,
+                        AppOpsManager.OP_FLAG_SELF);
+                mHistoricalRegistry.incrementOpAccessedCount(opCode, uid, packageName,
+                        uidState.state, AppOpsManager.OP_FLAG_SELF);
+
                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
             }
             op.startNesting++;
@@ -2161,7 +2201,7 @@
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
-                Slog.wtf(TAG, "Operation not started: uid=" + op.uid + " pkg="
+                Slog.wtf(TAG, "Operation not started: uid=" + op.uidState.uid + " pkg="
                         + op.packageName + " op=" + AppOpsManager.opToName(op.op));
                 return;
             }
@@ -2272,16 +2312,24 @@
     }
 
     void finishOperationLocked(Op op, boolean finishNested) {
+        final int opCode = op.op;
+        final int uid = op.uidState.uid;
         if (op.startNesting <= 1 || finishNested) {
             if (op.startNesting == 1 || finishNested) {
-                op.duration = (int)(SystemClock.elapsedRealtime() - op.startRealtime);
-                mHistoricalRegistry.increaseOpAccessDuration(op.op, op.uid, op.packageName,
-                        op.uidState.state, op.duration);
-                op.time[op.uidState.state] = System.currentTimeMillis();
+                // We don't support proxy long running ops (start/stop)
+                final long duration = SystemClock.elapsedRealtime() - op.startRealtime;
+                op.finished(System.currentTimeMillis(), duration, op.uidState.state,
+                        AppOpsManager.OP_FLAG_SELF);
+                mHistoricalRegistry.increaseOpAccessDuration(opCode, uid, op.packageName,
+                        op.uidState.state, AppOpsManager.OP_FLAG_SELF, duration);
             } else {
-                Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg "
-                        + op.packageName + " code " + op.op + " time=" + op.time
-                        + " duration=" + op.duration + " nesting=" + op.startNesting);
+                final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
+                    op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+                Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg "
+                        + op.packageName + " code " + opCode + " time="
+                        + entry.getLastAccessTime(OP_FLAGS_ALL)
+                        + " duration=" + entry.getLastDuration(MAX_PRIORITY_UID_STATE,
+                        MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL) + " nesting=" + op.startNesting);
             }
             if (op.startNesting >= 1) {
                 op.uidState.startNesting -= op.startNesting;
@@ -2311,7 +2359,7 @@
         throw new IllegalArgumentException("Bad operation #" + op);
     }
 
-    private UidState getUidStateLocked(int uid, boolean edit) {
+    private @NonNull UidState getUidStateLocked(int uid, boolean edit) {
         UidState uidState = mUidStates.get(uid);
         if (uidState == null) {
             if (!edit) {
@@ -2335,8 +2383,8 @@
     }
 
     private void commitUidPendingStateLocked(UidState uidState) {
-        final boolean lastForeground = uidState.state <= UID_STATE_LAST_NON_RESTRICTED;
-        final boolean nowForeground = uidState.pendingState <= UID_STATE_LAST_NON_RESTRICTED;
+        final boolean lastForeground = uidState.state <= UID_STATE_MAX_LAST_NON_RESTRICTED;
+        final boolean nowForeground = uidState.pendingState <= UID_STATE_MAX_LAST_NON_RESTRICTED;
         uidState.state = uidState.pendingState;
         uidState.pendingStateCommitTime = 0;
         if (uidState.hasForegroundWatchers && lastForeground != nowForeground) {
@@ -2345,7 +2393,15 @@
                     continue;
                 }
                 final int code = uidState.foregroundOps.keyAt(fgi);
-
+                // For location ops we consider fg state only if the fg service
+                // is of location type, for all other ops any fg service will do.
+                final long resolvedLastRestrictedUidState = resolveFirstUnrestrictedUidState(code);
+                final boolean resolvedLastFg = uidState.state <= resolvedLastRestrictedUidState;
+                final boolean resolvedNowBg = uidState.pendingState
+                        <= resolvedLastRestrictedUidState;
+                if (resolvedLastFg == resolvedNowBg) {
+                    continue;
+                }
                 final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(code);
                 if (callbacks != null) {
                     for (int cbi = callbacks.size() - 1; cbi >= 0; cbi--) {
@@ -2360,8 +2416,10 @@
                         if (uidState.pkgOps != null) {
                             for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
                                 final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
-                                if (doAllPackages || (op != null
-                                        && op.mode == AppOpsManager.MODE_FOREGROUND)) {
+                                if (op == null) {
+                                    continue;
+                                }
+                                if (doAllPackages || op.mode == AppOpsManager.MODE_FOREGROUND) {
                                     mHandler.sendMessage(PooledLambda.obtainMessage(
                                             AppOpsService::notifyOpChanged,
                                             this, callback, code, uidState.uid,
@@ -2651,7 +2709,7 @@
                 final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
                 if (idx >= 0) {
                     uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
-                            uidState.opModes.valueAt(idx));
+                        uidState.opModes.valueAt(idx));
                 }
             }
             if (uidState.pkgOps == null) {
@@ -2664,7 +2722,7 @@
                     final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
                     if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
                         final Op copy = new Op(op.uidState, op.packageName,
-                                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
+                            AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
                         copy.mode = op.mode;
                         ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
                         changed = true;
@@ -2692,7 +2750,7 @@
         scheduleFastWriteLocked();
     }
 
-    void readUidOps(XmlPullParser parser) throws NumberFormatException,
+    private void readUidOps(XmlPullParser parser) throws NumberFormatException,
             XmlPullParserException, IOException {
         final int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
         int outerDepth = parser.getDepth();
@@ -2720,8 +2778,8 @@
         }
     }
 
-    void readPackage(XmlPullParser parser) throws NumberFormatException,
-            XmlPullParserException, IOException {
+    private void readPackage(XmlPullParser parser)
+            throws NumberFormatException, XmlPullParserException, IOException {
         String pkgName = parser.getAttributeValue(null, "n");
         int outerDepth = parser.getDepth();
         int type;
@@ -2742,9 +2800,10 @@
         }
     }
 
-    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
-            XmlPullParserException, IOException {
+    private void readUid(XmlPullParser parser, String pkgName)
+            throws NumberFormatException, XmlPullParserException, IOException {
         int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
+        final UidState uidState = getUidStateLocked(uid, true);
         String isPrivilegedString = parser.getAttributeValue(null, "p");
         boolean isPrivileged = false;
         if (isPrivilegedString == null) {
@@ -2774,113 +2833,73 @@
             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                 continue;
             }
-
             String tagName = parser.getName();
             if (tagName.equals("op")) {
-                UidState uidState = getUidStateLocked(uid, true);
-                if (uidState.pkgOps == null) {
-                    uidState.pkgOps = new ArrayMap<>();
-                }
-
-                Op op = new Op(uidState, pkgName,
-                        Integer.parseInt(parser.getAttributeValue(null, "n")));
-
-                for (int i = parser.getAttributeCount()-1; i >= 0; i--) {
-                    final String name = parser.getAttributeName(i);
-                    final String value = parser.getAttributeValue(i);
-                    switch (name) {
-                        case "m":
-                            op.mode = Integer.parseInt(value);
-                            break;
-                        case "d":
-                            op.duration = Integer.parseInt(value);
-                            break;
-                        case "pu":
-                            op.proxyUid = Integer.parseInt(value);
-                            break;
-                        case "pp":
-                            op.proxyPackageName = value;
-                            break;
-                        case "tp":
-                            op.time[AppOpsManager.UID_STATE_PERSISTENT] = Long.parseLong(value);
-                            break;
-                        case "tt":
-                            op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
-                            break;
-                        case "tfsl":
-                            op.time[AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION] =
-                                    Long.parseLong(value);
-                            break;
-                        case "tfs":
-                            op.time[AppOpsManager.UID_STATE_FOREGROUND_SERVICE] =
-                                    Long.parseLong(value);
-                            break;
-                        case "tf":
-                            op.time[AppOpsManager.UID_STATE_FOREGROUND] = Long.parseLong(value);
-                            break;
-                        case "tb":
-                            op.time[AppOpsManager.UID_STATE_BACKGROUND] = Long.parseLong(value);
-                            break;
-                        case "tc":
-                            op.time[AppOpsManager.UID_STATE_CACHED] = Long.parseLong(value);
-                            break;
-                        case "rp":
-                            op.rejectTime[AppOpsManager.UID_STATE_PERSISTENT] =
-                                    Long.parseLong(value);
-                            break;
-                        case "rt":
-                            op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
-                            break;
-                        case "rfsl":
-                            op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION] =
-                                    Long.parseLong(value);
-                            break;
-                        case "rfs":
-                            op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND_SERVICE] =
-                                    Long.parseLong(value);
-                            break;
-                        case "rf":
-                            op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND] =
-                                    Long.parseLong(value);
-                            break;
-                        case "rb":
-                            op.rejectTime[AppOpsManager.UID_STATE_BACKGROUND] =
-                                    Long.parseLong(value);
-                            break;
-                        case "rc":
-                            op.rejectTime[AppOpsManager.UID_STATE_CACHED] =
-                                    Long.parseLong(value);
-                            break;
-                        case "t":
-                            // Backwards compat.
-                            op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
-                            break;
-                        case "r":
-                            // Backwards compat.
-                            op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
-                            break;
-                        default:
-                            Slog.w(TAG, "Unknown attribute in 'op' tag: " + name);
-                            break;
-                    }
-                }
-
-                Ops ops = uidState.pkgOps.get(pkgName);
-                if (ops == null) {
-                    ops = new Ops(pkgName, uidState, isPrivileged);
-                    uidState.pkgOps.put(pkgName, ops);
-                }
-                ops.put(op.op, op);
+                readOp(parser, uidState, pkgName, isPrivileged);
             } else {
                 Slog.w(TAG, "Unknown element under <pkg>: "
                         + parser.getName());
                 XmlUtils.skipCurrentTag(parser);
             }
         }
-        UidState uidState = getUidStateLocked(uid, false);
-        if (uidState != null) {
-            uidState.evalForegroundOps(mOpModeWatchers);
+        uidState.evalForegroundOps(mOpModeWatchers);
+    }
+
+    private void readOp(XmlPullParser parser, @NonNull UidState uidState,
+            @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
+            XmlPullParserException, IOException {
+        Op op = new Op(uidState, pkgName,
+                Integer.parseInt(parser.getAttributeValue(null, "n")));
+
+        final int mode = XmlUtils.readIntAttribute(parser, "m",
+                AppOpsManager.opToDefaultMode(op.op));
+        op.mode = mode;
+
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            String tagName = parser.getName();
+            if (tagName.equals("st")) {
+                final long key = XmlUtils.readLongAttribute(parser, "n");
+
+                final int flags = AppOpsManager.extractFlagsFromKey(key);
+                final int state = AppOpsManager.extractUidStateFromKey(key);
+
+                final long accessTime = XmlUtils.readLongAttribute(parser, "t", 0);
+                final long rejectTime = XmlUtils.readLongAttribute(parser, "r", 0);
+                final long accessDuration = XmlUtils.readLongAttribute(parser, "d", 0);
+                final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
+                final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", 0);
+
+                if (accessTime > 0) {
+                    op.accessed(accessTime, proxyUid, proxyPkg, state, flags);
+                }
+                if (rejectTime > 0) {
+                    op.rejected(rejectTime, proxyUid, proxyPkg, state, flags);
+                }
+                if (accessDuration > 0) {
+                    op.running(accessTime, accessDuration, state, flags);
+                }
+            } else {
+                Slog.w(TAG, "Unknown element under <op>: "
+                        + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
         }
+
+        if (uidState.pkgOps == null) {
+            uidState.pkgOps = new ArrayMap<>();
+        }
+        Ops ops = uidState.pkgOps.get(pkgName);
+        if (ops == null) {
+            ops = new Ops(pkgName, uidState, isPrivileged);
+            uidState.pkgOps.put(pkgName, ops);
+        }
+        ops.put(op.op, op);
     }
 
     void writeState() {
@@ -2955,30 +2974,53 @@
                             if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
                                 out.attribute(null, "m", Integer.toString(op.getMode()));
                             }
-                            for (int k = 0; k < _NUM_UID_STATE; k++) {
-                                final long time = op.getLastTimeFor(k);
-                                if (time != 0) {
-                                    out.attribute(null, UID_STATE_TIME_ATTRS[k],
-                                            Long.toString(time));
+
+                            final LongSparseArray keys = op.collectKeys();
+                            if (keys == null || keys.size() <= 0) {
+                                continue;
+                            }
+
+                            final int keyCount = keys.size();
+                            for (int k = 0; k < keyCount; k++) {
+                                final long key = keys.keyAt(k);
+
+                                final int uidState = AppOpsManager.extractUidStateFromKey(key);
+                                final int flags = AppOpsManager.extractFlagsFromKey(key);
+
+                                final long accessTime = op.getLastAccessTime(
+                                        uidState, uidState, flags);
+                                final long rejectTime = op.getLastRejectTime(
+                                        uidState, uidState, flags);
+                                final long accessDuration = op.getLastDuration(
+                                        uidState, uidState, flags);
+                                final String proxyPkg = op.getProxyPackageName(uidState, flags);
+                                final int proxyUid = op.getProxyUid(uidState, flags);
+
+                                if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
+                                        && proxyPkg == null && proxyUid < 0) {
+                                    continue;
                                 }
-                                final long rejectTime = op.getLastRejectTimeFor(k);
-                                if (rejectTime != 0) {
-                                    out.attribute(null, UID_STATE_REJECT_ATTRS[k],
-                                            Long.toString(rejectTime));
+
+                                out.startTag(null, "st");
+                                out.attribute(null, "n", Long.toString(key));
+                                if (accessTime > 0) {
+                                    out.attribute(null, "t", Long.toString(accessTime));
                                 }
+                                if (rejectTime > 0) {
+                                    out.attribute(null, "r", Long.toString(rejectTime));
+                                }
+                                if (accessDuration > 0) {
+                                    out.attribute(null, "d", Long.toString(accessDuration));
+                                }
+                                if (proxyPkg != null) {
+                                    out.attribute(null, "pp", proxyPkg);
+                                }
+                                if (proxyUid >= 0) {
+                                    out.attribute(null, "pu", Integer.toString(proxyUid));
+                                }
+                                out.endTag(null, "st");
                             }
-                            int dur = op.getDuration();
-                            if (dur != 0) {
-                                out.attribute(null, "d", Integer.toString(dur));
-                            }
-                            int proxyUid = op.getProxyUid();
-                            if (proxyUid != -1) {
-                                out.attribute(null, "pu", Integer.toString(proxyUid));
-                            }
-                            String proxyPackageName = op.getProxyPackageName();
-                            if (proxyPackageName != null) {
-                                out.attribute(null, "pp", proxyPackageName);
-                            }
+
                             out.endTag(null, "op");
                         }
                         out.endTag(null, "uid");
@@ -3462,32 +3504,80 @@
         pw.println("    Limit output to data associated with the given package name.");
         pw.println("  --watchers");
         pw.println("    Only output the watcher sections.");
+        pw.println("  --history");
+        pw.println("    Output the historical data.");
     }
 
-    private void dumpTimesLocked(PrintWriter pw, String firstPrefix, String prefix, long[] times,
-            long now, SimpleDateFormat sdf, Date date) {
-        boolean hasTime = false;
-        for (int i = 0; i < _NUM_UID_STATE; i++) {
-            if (times[i] != 0) {
-                hasTime = true;
-                break;
-            }
-        }
-        if (!hasTime) {
+    private void dumpStatesLocked(@NonNull PrintWriter pw, @NonNull Op op,
+            long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
+
+        final OpEntry entry = new OpEntry(op.op, op.running, op.mode, op.mAccessTimes,
+            op.mRejectTimes, op.mDurations, op.mProxyUids, op.mProxyPackageNames);
+
+        final LongSparseArray keys = entry.collectKeys();
+        if (keys == null || keys.size() <= 0) {
             return;
         }
-        boolean first = true;
-        for (int i = 0; i < _NUM_UID_STATE; i++) {
-            if (times[i] != 0) {
-                pw.print(first ? firstPrefix : prefix);
-                first = false;
-                pw.print(UID_STATE_NAMES[i]);
-                pw.print(" = ");
-                date.setTime(times[i]);
+
+        final int keyCount = keys.size();
+        for (int k = 0; k < keyCount; k++) {
+            final long key = keys.keyAt(k);
+
+            final int uidState = AppOpsManager.extractUidStateFromKey(key);
+            final int flags = AppOpsManager.extractFlagsFromKey(key);
+
+            final long accessTime = entry.getLastAccessTime(
+                    uidState, uidState, flags);
+            final long rejectTime = entry.getLastRejectTime(
+                    uidState, uidState, flags);
+            final long accessDuration = entry.getLastDuration(
+                    uidState, uidState, flags);
+            final String proxyPkg = entry.getProxyPackageName(uidState, flags);
+            final int proxyUid = entry.getProxyUid(uidState, flags);
+
+            if (accessTime > 0) {
+                pw.print(prefix);
+                pw.print("Access: ");
+                pw.print(AppOpsManager.keyToString(key));
+                pw.print(" ");
+                date.setTime(accessTime);
                 pw.print(sdf.format(date));
                 pw.print(" (");
-                TimeUtils.formatDuration(times[i]-now, pw);
-                pw.println(")");
+                TimeUtils.formatDuration(accessTime - now, pw);
+                pw.print(")");
+                if (accessDuration > 0) {
+                    pw.print(" duration=");
+                    TimeUtils.formatDuration(accessDuration, pw);
+                }
+                if (proxyUid >= 0) {
+                    pw.print(" proxy[");
+                    pw.print("uid=");
+                    pw.print(proxyUid);
+                    pw.print(", pkg=");
+                    pw.print(proxyPkg);
+                    pw.print("]");
+                }
+                pw.println();
+            }
+
+            if (rejectTime > 0) {
+                pw.print(prefix);
+                pw.print("Reject: ");
+                pw.print(AppOpsManager.keyToString(key));
+                date.setTime(rejectTime);
+                pw.print(sdf.format(date));
+                pw.print(" (");
+                TimeUtils.formatDuration(rejectTime - now, pw);
+                pw.print(")");
+                if (proxyUid >= 0) {
+                    pw.print(" proxy[");
+                    pw.print("uid=");
+                    pw.print(proxyUid);
+                    pw.print(", pkg=");
+                    pw.print(proxyPkg);
+                    pw.print("]");
+                }
+                pw.println();
             }
         }
     }
@@ -3501,6 +3591,7 @@
         int dumpUid = Process.INVALID_UID;
         int dumpMode = -1;
         boolean dumpWatchers = false;
+        boolean dumpHistory = false;
 
         if (args != null) {
             for (int i=0; i<args.length; i++) {
@@ -3550,6 +3641,8 @@
                     }
                 } else if ("--watchers".equals(arg)) {
                     dumpWatchers = true;
+                } else if ("--history".equals(arg)) {
+                    dumpHistory = true;
                 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
                     pw.println("Unknown option: " + arg);
                     return;
@@ -3562,7 +3655,9 @@
 
         synchronized (this) {
             pw.println("Current AppOps Service state:");
-            mConstants.dump(pw);
+            if (!dumpHistory && !dumpWatchers) {
+                mConstants.dump(pw);
+            }
             pw.println();
             final long now = System.currentTimeMillis();
             final long nowElapsed = SystemClock.elapsedRealtime();
@@ -3571,7 +3666,7 @@
             final Date date = new Date();
             boolean needSep = false;
             if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null
-                    && !dumpWatchers) {
+                    && !dumpWatchers && !dumpHistory) {
                 pw.println("  Profile owners:");
                 for (int poi = 0; poi < mProfileOwners.size(); poi++) {
                     pw.print("    User #");
@@ -3582,7 +3677,7 @@
                 }
                 pw.println();
             }
-            if (mOpModeWatchers.size() > 0) {
+            if (mOpModeWatchers.size() > 0 && !dumpHistory) {
                 boolean printedHeader = false;
                 for (int i=0; i<mOpModeWatchers.size(); i++) {
                     if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
@@ -3612,7 +3707,7 @@
                     }
                 }
             }
-            if (mPackageModeWatchers.size() > 0 && dumpOp < 0) {
+            if (mPackageModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
                 boolean printedHeader = false;
                 for (int i=0; i<mPackageModeWatchers.size(); i++) {
                     if (dumpPackage != null && !dumpPackage.equals(mPackageModeWatchers.keyAt(i))) {
@@ -3632,7 +3727,7 @@
                     }
                 }
             }
-            if (mModeWatchers.size() > 0 && dumpOp < 0) {
+            if (mModeWatchers.size() > 0 && dumpOp < 0 && !dumpHistory) {
                 boolean printedHeader = false;
                 for (int i=0; i<mModeWatchers.size(); i++) {
                     final ModeCallback cb = mModeWatchers.valueAt(i);
@@ -3730,7 +3825,7 @@
                     pw.println(cb);
                 }
             }
-            if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers) {
+            if (mClients.size() > 0 && dumpMode < 0 && !dumpWatchers && !dumpHistory) {
                 needSep = true;
                 boolean printedHeader = false;
                 for (int i=0; i<mClients.size(); i++) {
@@ -3759,7 +3854,7 @@
                                 pw.println("      Started ops:");
                                 printedStarted = true;
                             }
-                            pw.print("        "); pw.print("uid="); pw.print(op.uid);
+                            pw.print("        "); pw.print("uid="); pw.print(op.uidState.uid);
                             pw.print(" pkg="); pw.print(op.packageName);
                             pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
                         }
@@ -3767,7 +3862,7 @@
                 }
             }
             if (mAudioRestrictions.size() > 0 && dumpOp < 0 && dumpPackage != null
-                    && dumpMode < 0 && !dumpWatchers) {
+                    && dumpMode < 0 && !dumpWatchers && !dumpWatchers) {
                 boolean printedHeader = false;
                 for (int o=0; o<mAudioRestrictions.size(); o++) {
                     final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o));
@@ -3800,7 +3895,7 @@
                 final SparseIntArray opModes = uidState.opModes;
                 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
 
-                if (dumpWatchers) {
+                if (dumpWatchers || dumpHistory) {
                     continue;
                 }
                 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
@@ -3847,10 +3942,10 @@
 
                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
                 pw.print("    state=");
-                pw.println(UID_STATE_NAMES[uidState.state]);
+                pw.println(AppOpsManager.getUidStateName(uidState.state));
                 if (uidState.state != uidState.pendingState) {
                     pw.print("    pendingState=");
-                    pw.println(UID_STATE_NAMES[uidState.pendingState]);
+                    pw.println(AppOpsManager.getUidStateName(uidState.pendingState));
                 }
                 if (uidState.pendingStateCommitTime != 0) {
                     pw.print("    pendingStateCommitTime=");
@@ -3906,7 +4001,8 @@
                     boolean printedPackage = false;
                     for (int j=0; j<ops.size(); j++) {
                         final Op op = ops.valueAt(j);
-                        if (dumpOp >= 0 && dumpOp != op.op) {
+                        final int opCode = op.op;
+                        if (dumpOp >= 0 && dumpOp != opCode) {
                             continue;
                         }
                         if (dumpMode >= 0 && dumpMode != op.mode) {
@@ -3916,32 +4012,23 @@
                             pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
                             printedPackage = true;
                         }
-                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
+                        pw.print("      "); pw.print(AppOpsManager.opToName(opCode));
                         pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
-                        final int switchOp = AppOpsManager.opToSwitch(op.op);
-                        if (switchOp != op.op) {
+                        final int switchOp = AppOpsManager.opToSwitch(opCode);
+                        if (switchOp != opCode) {
                             pw.print(" / switch ");
                             pw.print(AppOpsManager.opToName(switchOp));
                             final Op switchObj = ops.get(switchOp);
-                            int mode = switchObj != null
-                                    ? switchObj.mode : AppOpsManager.opToDefaultMode(switchOp);
+                            int mode = switchObj != null ? switchObj.mode
+                                    : AppOpsManager.opToDefaultMode(switchOp);
                             pw.print("="); pw.print(AppOpsManager.modeToName(mode));
                         }
                         pw.println("): ");
-                        dumpTimesLocked(pw,
-                                "          Access: ",
-                                "                  ", op.time, now, sdf, date);
-                        dumpTimesLocked(pw,
-                                "          Reject: ",
-                                "                  ", op.rejectTime, now, sdf, date);
-                        if (op.duration == -1) {
+                        dumpStatesLocked(pw, op, now, sdf, date, "          ");
+                        if (op.running) {
                             pw.print("          Running start at: ");
                             TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
                             pw.println();
-                        } else if (op.duration != 0) {
-                            pw.print("          duration=");
-                            TimeUtils.formatDuration(op.duration, pw);
-                            pw.println();
                         }
                         if (op.startNesting != 0) {
                             pw.print("          startNesting=");
@@ -3960,7 +4047,7 @@
                 ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
                 boolean printedTokenHeader = false;
 
-                if (dumpMode >= 0 || dumpWatchers) {
+                if (dumpMode >= 0 || dumpWatchers || dumpHistory) {
                     continue;
                 }
 
@@ -4044,7 +4131,9 @@
         }
 
         // Must not hold the appops lock
-        mHistoricalRegistry.dump("  ", pw, dumpUid, dumpPackage, dumpOp);
+        if (dumpHistory && !dumpWatchers) {
+            mHistoricalRegistry.dump("  ", pw, dumpUid, dumpPackage, dumpOp);
+        }
     }
 
     private static final class Restriction {
@@ -4158,7 +4247,7 @@
                 final ClientState client = mClients.valueAt(i);
                 for (int j = client.mStartedOps.size() - 1; j >= 0; j--) {
                     final Op op = client.mStartedOps.get(j);
-                    if (op.op == code && op.uid == uid) return true;
+                    if (op.op == code && op.uidState.uid == uid) return true;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 4485a54..d723c7b 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -23,6 +23,7 @@
 import android.app.AppOpsManager.HistoricalOps;
 import android.app.AppOpsManager.HistoricalPackageOps;
 import android.app.AppOpsManager.HistoricalUidOps;
+import android.app.AppOpsManager.OpFlags;
 import android.app.AppOpsManager.UidState;
 import android.content.ContentResolver;
 import android.database.ContentObserver;
@@ -37,6 +38,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArraySet;
+import android.util.LongSparseArray;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.Xml;
@@ -144,7 +146,7 @@
      * Whether history is enabled.
      */
     @GuardedBy("mInMemoryLock")
-    private int mMode = AppOpsManager.HISTORICAL_MODE_DISABLED;
+    private int mMode = AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE;
 
     /**
      * This granularity has been chosen to allow clean delineation for intervals
@@ -297,20 +299,20 @@
         }
     }
 
-    @Nullable void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
+    void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
             @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
-            @NonNull RemoteCallback callback) {
+            @OpFlags int flags, @NonNull RemoteCallback callback) {
         final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis);
         mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames,
-                beginTimeMillis, endTimeMillis);
+                beginTimeMillis, endTimeMillis, flags);
         final Bundle payload = new Bundle();
         payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, result);
         callback.sendResult(payload);
     }
 
-    @Nullable void getHistoricalOps(int uid, @NonNull String packageName,
+    void getHistoricalOps(int uid, @NonNull String packageName,
             @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
-            @NonNull RemoteCallback callback) {
+            @OpFlags int flags, @NonNull RemoteCallback callback) {
         final long currentTimeMillis = System.currentTimeMillis();
         if (endTimeMillis == Long.MAX_VALUE) {
             endTimeMillis = currentTimeMillis;
@@ -326,6 +328,8 @@
         synchronized (mOnDiskLock) {
             final List<HistoricalOps> pendingWrites;
             final HistoricalOps currentOps;
+            boolean collectOpsFromDisk;
+
             synchronized (mInMemoryLock) {
                 currentOps = getUpdatedPendingHistoricalOpsMLocked(currentTimeMillis);
                 if (!(inMemoryAdjBeginTimeMillis >= currentOps.getEndTimeMillis()
@@ -338,10 +342,11 @@
                 }
                 pendingWrites = new ArrayList<>(mPendingWrites);
                 mPendingWrites.clear();
+                collectOpsFromDisk = inMemoryAdjEndTimeMillis > currentOps.getEndTimeMillis();
             }
 
             // If the query was only for in-memory state - done.
-            if (inMemoryAdjEndTimeMillis > currentOps.getEndTimeMillis()) {
+            if (collectOpsFromDisk) {
                 // If there is a write in flight we need to force it now
                 persistPendingHistory(pendingWrites);
                 // Collect persisted state.
@@ -352,7 +357,7 @@
                 final long onDiskAdjEndTimeMillis = Math.max(inMemoryAdjEndTimeMillis
                         - onDiskAndInMemoryOffsetMillis, 0);
                 mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames,
-                        onDiskAdjBeginTimeMillis, onDiskAdjEndTimeMillis);
+                        onDiskAdjBeginTimeMillis, onDiskAdjEndTimeMillis, flags);
             }
 
             // Rebase the result time to be since epoch.
@@ -366,32 +371,31 @@
     }
 
     void incrementOpAccessedCount(int op, int uid, @NonNull String packageName,
-            @UidState int uidState) {
+            @UidState int uidState, @OpFlags int flags) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
-                        .increaseAccessCount(op, uid, packageName, uidState, 1);
-
+                        .increaseAccessCount(op, uid, packageName, uidState, flags, 1);
             }
         }
     }
 
     void incrementOpRejected(int op, int uid, @NonNull String packageName,
-            @UidState int uidState) {
+            @UidState int uidState, @OpFlags int flags) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
-                        .increaseRejectCount(op, uid, packageName, uidState, 1);
+                        .increaseRejectCount(op, uid, packageName, uidState, flags, 1);
             }
         }
     }
 
     void increaseOpAccessDuration(int op, int uid, @NonNull String packageName,
-            @UidState int uidState, long increment) {
+            @UidState int uidState, @OpFlags int flags, long increment) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
-                        .increaseAccessDuration(op, uid, packageName, uidState, increment);
+                        .increaseAccessDuration(op, uid, packageName, uidState, flags, increment);
             }
         }
     }
@@ -593,20 +597,20 @@
         private static final String TAG_HISTORY = "history";
         private static final String TAG_OPS = "ops";
         private static final String TAG_UID = "uid";
-        private static final String TAG_PACKAGE = "package";
+        private static final String TAG_PACKAGE = "pkg";
         private static final String TAG_OP = "op";
-        private static final String TAG_STATE = "state";
+        private static final String TAG_STATE = "st";
 
-        private static final String ATTR_VERSION = "version";
-        private static final String ATTR_NAME = "name";
-        private static final String ATTR_ACCESS_COUNT = "accessCount";
-        private static final String ATTR_REJECT_COUNT = "rejectCount";
-        private static final String ATTR_ACCESS_DURATION = "accessDuration";
-        private static final String ATTR_BEGIN_TIME = "beginTime";
-        private static final String ATTR_END_TIME = "endTime";
-        private static final String ATTR_OVERFLOW = "overflow";
+        private static final String ATTR_VERSION = "ver";
+        private static final String ATTR_NAME = "na";
+        private static final String ATTR_ACCESS_COUNT = "ac";
+        private static final String ATTR_REJECT_COUNT = "rc";
+        private static final String ATTR_ACCESS_DURATION = "du";
+        private static final String ATTR_BEGIN_TIME = "beg";
+        private static final String ATTR_END_TIME = "end";
+        private static final String ATTR_OVERFLOW = "ov";
 
-        private static final int CURRENT_VERSION = 1;
+        private static final int CURRENT_VERSION = 2;
 
         private final long mBaseSnapshotInterval;
         private final long mIntervalCompressionMultiplier;
@@ -657,7 +661,8 @@
         @Nullable List<HistoricalOps> readHistoryRawDLocked() {
             return collectHistoricalOpsBaseDLocked(Process.INVALID_UID /*filterUid*/,
                     null /*filterPackageName*/, null /*filterOpNames*/,
-                    0 /*filterBeginTimeMills*/, Long.MAX_VALUE /*filterEndTimeMills*/);
+                    0 /*filterBeginTimeMills*/, Long.MAX_VALUE /*filterEndTimeMills*/,
+                    AppOpsManager.OP_FLAGS_ALL);
         }
 
         @Nullable List<HistoricalOps> readHistoryDLocked() {
@@ -697,9 +702,10 @@
 
         private void collectHistoricalOpsDLocked(@NonNull HistoricalOps currentOps,
                 int filterUid, @NonNull String filterPackageName, @Nullable String[] filterOpNames,
-                long filterBeingMillis, long filterEndMillis) {
+                long filterBeingMillis, long filterEndMillis, @OpFlags int filterFlags) {
             final List<HistoricalOps> readOps = collectHistoricalOpsBaseDLocked(filterUid,
-                    filterPackageName, filterOpNames, filterBeingMillis, filterEndMillis);
+                    filterPackageName, filterOpNames, filterBeingMillis, filterEndMillis,
+                    filterFlags);
             if (readOps != null) {
                 final int readCount = readOps.size();
                 for (int i = 0; i < readCount; i++) {
@@ -711,7 +717,7 @@
 
         private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsBaseDLocked(
                 int filterUid, @NonNull String filterPackageName, @Nullable String[] filterOpNames,
-                long filterBeginTimeMillis, long filterEndTimeMillis) {
+                long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags) {
             File baseDir = null;
             try {
                 baseDir = mHistoricalAppOpsDir.startRead();
@@ -724,8 +730,8 @@
                 final long[] globalContentOffsetMillis = {0};
                 final LinkedList<HistoricalOps> ops = collectHistoricalOpsRecursiveDLocked(
                         baseDir, filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
-                        filterEndTimeMillis, globalContentOffsetMillis, null /*outOps*/,
-                        0 /*depth*/, historyFiles);
+                        filterEndTimeMillis, filterFlags, globalContentOffsetMillis,
+                        null /*outOps*/, 0 /*depth*/, historyFiles);
                 if (DEBUG) {
                     filesInvariant.stopTracking(baseDir);
                 }
@@ -741,7 +747,8 @@
         private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsRecursiveDLocked(
                 @NonNull File baseDir, int filterUid, @NonNull String filterPackageName,
                 @Nullable String[] filterOpNames, long filterBeginTimeMillis,
-                long filterEndTimeMillis, @NonNull long[] globalContentOffsetMillis,
+                long filterEndTimeMillis, @OpFlags int filterFlags,
+                @NonNull long[] globalContentOffsetMillis,
                 @Nullable LinkedList<HistoricalOps> outOps, int depth,
                 @NonNull Set<String> historyFiles)
                 throws IOException, XmlPullParserException {
@@ -757,7 +764,7 @@
             final List<HistoricalOps> readOps = readHistoricalOpsLocked(baseDir,
                     previousIntervalEndMillis, currentIntervalEndMillis, filterUid,
                     filterPackageName, filterOpNames, filterBeginTimeMillis, filterEndTimeMillis,
-                    globalContentOffsetMillis, depth, historyFiles);
+                    filterFlags, globalContentOffsetMillis, depth, historyFiles);
 
             // Empty is a special signal to stop diving
             if (readOps != null && readOps.isEmpty()) {
@@ -767,7 +774,7 @@
             // Collect older historical data from subsequent levels
             outOps = collectHistoricalOpsRecursiveDLocked(
                     baseDir, filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
-                    filterEndTimeMillis, globalContentOffsetMillis, outOps, depth + 1,
+                    filterEndTimeMillis, filterFlags, globalContentOffsetMillis, outOps, depth + 1,
                     historyFiles);
 
             // Make older historical data relative to the current historical level
@@ -836,22 +843,24 @@
                     previousIntervalEndMillis, currentIntervalEndMillis,
                     Process.INVALID_UID /*filterUid*/, null /*filterPackageName*/,
                     null /*filterOpNames*/, Long.MIN_VALUE /*filterBeginTimeMillis*/,
-                    Long.MAX_VALUE /*filterEndTimeMillis*/, null, depth,
-                    null /*historyFiles*/);
+                    Long.MAX_VALUE /*filterEndTimeMillis*/, AppOpsManager.OP_FLAGS_ALL,
+                    null, depth, null /*historyFiles*/);
 
             if (DEBUG) {
                 enforceOpsWellFormed(existingOps);
             }
 
             // Offset existing ops to account for elapsed time
-            final int existingOpCount = existingOps.size();
-            if (existingOpCount > 0) {
-                // Compute elapsed time
-                final long elapsedTimeMillis = passedOps.get(passedOps.size() - 1)
+            if (existingOps != null) {
+                final int existingOpCount = existingOps.size();
+                if (existingOpCount > 0) {
+                    // Compute elapsed time
+                    final long elapsedTimeMillis = passedOps.get(passedOps.size() - 1)
                         .getEndTimeMillis();
-                for (int i = 0; i < existingOpCount; i++) {
-                    final HistoricalOps existingOp = existingOps.get(i);
-                    existingOp.offsetBeginAndEndTime(elapsedTimeMillis);
+                    for (int i = 0; i < existingOpCount; i++) {
+                        final HistoricalOps existingOp = existingOps.get(i);
+                        existingOp.offsetBeginAndEndTime(elapsedTimeMillis);
+                    }
                 }
             }
 
@@ -864,9 +873,10 @@
             // Consolidate passed ops at the current slot duration ensuring each snapshot is
             // full. To achieve this we put all passed and existing ops in a list and will
             // merge them to ensure each represents a snapshot at the current granularity.
-            final List<HistoricalOps> allOps = new LinkedList<>();
-            allOps.addAll(passedOps);
-            allOps.addAll(existingOps);
+            final List<HistoricalOps> allOps = new LinkedList<>(passedOps);
+            if (existingOps != null) {
+                allOps.addAll(existingOps);
+            }
 
             if (DEBUG) {
                 enforceOpsWellFormed(allOps);
@@ -944,10 +954,10 @@
                     overflowedOps, oldFileNames, depth + 1);
         }
 
-        private @NonNull List<HistoricalOps> readHistoricalOpsLocked(File baseDir,
-                long intervalBeginMillis, long intervalEndMillis, int filterUid,
-                @Nullable String filterPackageName, @Nullable String[] filterOpNames,
-                long filterBeginTimeMillis, long filterEndTimeMillis,
+        private @Nullable List<HistoricalOps> readHistoricalOpsLocked(File baseDir,
+                long intervalBeginMillis, long intervalEndMillis,
+                int filterUid, @Nullable String filterPackageName, @Nullable String[] filterOpNames,
+                long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
                 @Nullable long[] cumulativeOverflowMillis, int depth,
                 @NonNull Set<String> historyFiles)
                 throws IOException, XmlPullParserException {
@@ -973,12 +983,13 @@
                 }
             }
             return readHistoricalOpsLocked(file, filterUid, filterPackageName, filterOpNames,
-                    filterBeginTimeMillis, filterEndTimeMillis, cumulativeOverflowMillis);
+                    filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
+                    cumulativeOverflowMillis);
         }
 
         private @Nullable List<HistoricalOps> readHistoricalOpsLocked(@NonNull File file,
                 int filterUid, @Nullable String filterPackageName, @Nullable String[] filterOpNames,
-                long filterBeginTimeMillis, long filterEndTimeMillis,
+                long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
                 @Nullable long[] cumulativeOverflowMillis)
                 throws IOException, XmlPullParserException {
             if (DEBUG) {
@@ -989,13 +1000,22 @@
                 final XmlPullParser parser = Xml.newPullParser();
                 parser.setInput(stream, StandardCharsets.UTF_8.name());
                 XmlUtils.beginDocument(parser, TAG_HISTORY);
+
+                // We haven't released version 1 and have more detailed
+                // accounting - just nuke the current state
+                final int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION);
+                if (CURRENT_VERSION == 2 && version < CURRENT_VERSION) {
+                    throw new IllegalStateException("Dropping unsupported history "
+                            + "version 1 for file:" + file);
+                }
+
                 final long overflowMillis = XmlUtils.readLongAttribute(parser, ATTR_OVERFLOW, 0);
                 final int depth = parser.getDepth();
                 while (XmlUtils.nextElementWithin(parser, depth)) {
                     if (TAG_OPS.equals(parser.getName())) {
                         final HistoricalOps ops = readeHistoricalOpsDLocked(parser,
                                 filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
-                                filterEndTimeMillis, cumulativeOverflowMillis);
+                                filterEndTimeMillis, filterFlags, cumulativeOverflowMillis);
                         if (ops == null) {
                             continue;
                         }
@@ -1029,7 +1049,8 @@
         private @Nullable HistoricalOps readeHistoricalOpsDLocked(
                 @NonNull XmlPullParser parser, int filterUid, @Nullable String filterPackageName,
                 @Nullable String[] filterOpNames, long filterBeginTimeMillis,
-                long filterEndTimeMillis, @Nullable long[] cumulativeOverflowMillis)
+                long filterEndTimeMillis, @OpFlags int filterFlags,
+                @Nullable long[] cumulativeOverflowMillis)
                 throws IOException, XmlPullParserException {
             final long beginTimeMillis = XmlUtils.readLongAttribute(parser, ATTR_BEGIN_TIME, 0)
                     + (cumulativeOverflowMillis != null ? cumulativeOverflowMillis[0] : 0);
@@ -1045,6 +1066,10 @@
             }
             final long filteredBeginTimeMillis = Math.max(beginTimeMillis, filterBeginTimeMillis);
             final long filteredEndTimeMillis = Math.min(endTimeMillis, filterEndTimeMillis);
+            // // Keep reading as subsequent records may start matching
+            // if (filteredEndTimeMillis - filterBeginTimeMillis <= 0) {
+            //     return null;
+            // }
             final double filterScale = (double) (filteredEndTimeMillis - filteredBeginTimeMillis)
                     / (double) (endTimeMillis - beginTimeMillis);
             HistoricalOps ops = null;
@@ -1052,7 +1077,7 @@
             while (XmlUtils.nextElementWithin(parser, depth)) {
                 if (TAG_UID.equals(parser.getName())) {
                     final HistoricalOps returnedOps = readHistoricalUidOpsDLocked(ops, parser,
-                            filterUid, filterPackageName, filterOpNames, filterScale);
+                            filterUid, filterPackageName, filterOpNames, filterFlags, filterScale);
                     if (ops == null) {
                         ops = returnedOps;
                     }
@@ -1067,7 +1092,8 @@
         private @Nullable HistoricalOps readHistoricalUidOpsDLocked(
                 @Nullable HistoricalOps ops, @NonNull XmlPullParser parser, int filterUid,
                 @Nullable String filterPackageName, @Nullable String[] filterOpNames,
-                double filterScale) throws IOException, XmlPullParserException {
+                @OpFlags int filterFlags, double filterScale)
+                throws IOException, XmlPullParserException {
             final int uid = XmlUtils.readIntAttribute(parser, ATTR_NAME);
             if (filterUid != Process.INVALID_UID && filterUid != uid) {
                 XmlUtils.skipCurrentTag(parser);
@@ -1077,7 +1103,8 @@
             while (XmlUtils.nextElementWithin(parser, depth)) {
                 if (TAG_PACKAGE.equals(parser.getName())) {
                     final HistoricalOps returnedOps = readHistoricalPackageOpsDLocked(ops,
-                            uid, parser, filterPackageName, filterOpNames, filterScale);
+                            uid, parser, filterPackageName, filterOpNames, filterFlags,
+                            filterScale);
                     if (ops == null) {
                         ops = returnedOps;
                     }
@@ -1089,7 +1116,8 @@
         private @Nullable HistoricalOps readHistoricalPackageOpsDLocked(
                 @Nullable HistoricalOps ops, int uid, @NonNull XmlPullParser parser,
                 @Nullable String filterPackageName, @Nullable String[] filterOpNames,
-                double filterScale) throws IOException, XmlPullParserException {
+                @OpFlags int filterFlags, double filterScale)
+                throws IOException, XmlPullParserException {
             final String packageName = XmlUtils.readStringAttribute(parser, ATTR_NAME);
             if (filterPackageName != null && !filterPackageName.equals(packageName)) {
                 XmlUtils.skipCurrentTag(parser);
@@ -1099,7 +1127,7 @@
             while (XmlUtils.nextElementWithin(parser, depth)) {
                 if (TAG_OP.equals(parser.getName())) {
                     final HistoricalOps returnedOps = readHistoricalOpDLocked(ops, uid,
-                            packageName, parser, filterOpNames, filterScale);
+                            packageName, parser, filterOpNames, filterFlags, filterScale);
                     if (ops == null) {
                         ops = returnedOps;
                     }
@@ -1110,7 +1138,7 @@
 
         private @Nullable HistoricalOps readHistoricalOpDLocked(@Nullable HistoricalOps ops,
                 int uid, String packageName, @NonNull XmlPullParser parser,
-                @Nullable String[] filterOpNames, double filterScale)
+                @Nullable String[] filterOpNames, @OpFlags int filterFlags, double filterScale)
                 throws IOException, XmlPullParserException {
             final int op = XmlUtils.readIntAttribute(parser, ATTR_NAME);
             if (filterOpNames != null && !ArrayUtils.contains(filterOpNames,
@@ -1121,8 +1149,8 @@
             final int depth = parser.getDepth();
             while (XmlUtils.nextElementWithin(parser, depth)) {
                 if (TAG_STATE.equals(parser.getName())) {
-                    final HistoricalOps returnedOps = readUidStateDLocked(ops, uid,
-                            packageName, op, parser, filterScale);
+                    final HistoricalOps returnedOps = readStateDLocked(ops, uid,
+                            packageName, op, parser, filterFlags, filterScale);
                     if (ops == null) {
                         ops = returnedOps;
                     }
@@ -1131,10 +1159,15 @@
             return ops;
         }
 
-        private @Nullable HistoricalOps readUidStateDLocked(@Nullable HistoricalOps ops,
+        private @Nullable HistoricalOps readStateDLocked(@Nullable HistoricalOps ops,
                 int uid, String packageName, int op, @NonNull XmlPullParser parser,
-                double filterScale) throws IOException {
-            final int uidState = XmlUtils.readIntAttribute(parser, ATTR_NAME);
+                @OpFlags int filterFlags, double filterScale) throws IOException {
+            final long key = XmlUtils.readLongAttribute(parser, ATTR_NAME);
+            final int flags = AppOpsManager.extractFlagsFromKey(key) & filterFlags;
+            if (flags == 0) {
+                return null;
+            }
+            final int uidState = AppOpsManager.extractUidStateFromKey(key);
             long accessCount = XmlUtils.readLongAttribute(parser, ATTR_ACCESS_COUNT, 0);
             if (accessCount > 0) {
                 if (!Double.isNaN(filterScale)) {
@@ -1144,7 +1177,7 @@
                 if (ops == null) {
                     ops = new HistoricalOps(0, 0);
                 }
-                ops.increaseAccessCount(op, uid, packageName, uidState, accessCount);
+                ops.increaseAccessCount(op, uid, packageName, uidState, flags, accessCount);
             }
             long rejectCount = XmlUtils.readLongAttribute(parser, ATTR_REJECT_COUNT, 0);
             if (rejectCount > 0) {
@@ -1155,7 +1188,7 @@
                 if (ops == null) {
                     ops = new HistoricalOps(0, 0);
                 }
-                ops.increaseRejectCount(op, uid, packageName, uidState, rejectCount);
+                ops.increaseRejectCount(op, uid, packageName, uidState, flags, rejectCount);
             }
             long accessDuration =  XmlUtils.readLongAttribute(parser, ATTR_ACCESS_DURATION, 0);
             if (accessDuration > 0) {
@@ -1166,7 +1199,7 @@
                 if (ops == null) {
                     ops = new HistoricalOps(0, 0);
                 }
-                ops.increaseAccessDuration(op, uid, packageName, uidState, accessDuration);
+                ops.increaseAccessDuration(op, uid, packageName, uidState, flags, accessDuration);
             }
             return ops;
         }
@@ -1241,24 +1274,34 @@
 
         private void writeHistoricalOpDLocked(@NonNull HistoricalOp op,
                 @NonNull XmlSerializer serializer) throws IOException {
+            final LongSparseArray keys = op.collectKeys();
+            if (keys == null || keys.size() <= 0) {
+                return;
+            }
             serializer.startTag(null, TAG_OP);
             serializer.attribute(null, ATTR_NAME, Integer.toString(op.getOpCode()));
-            for (int uidState = 0; uidState < AppOpsManager._NUM_UID_STATE; uidState++) {
-                writeUidStateOnLocked(op, uidState, serializer);
+            final int keyCount = keys.size();
+            for (int i = 0; i < keyCount; i++) {
+                writeStateOnLocked(op, keys.keyAt(i), serializer);
             }
             serializer.endTag(null, TAG_OP);
         }
 
-        private void writeUidStateOnLocked(@NonNull HistoricalOp op, @UidState int uidState,
+        private void writeStateOnLocked(@NonNull HistoricalOp op, long key,
                 @NonNull XmlSerializer serializer) throws IOException {
-            final long accessCount = op.getAccessCount(uidState);
-            final long rejectCount = op.getRejectCount(uidState);
-            final long accessDuration = op.getAccessDuration(uidState);
-            if (accessCount == 0 && rejectCount == 0 && accessDuration == 0) {
+            final int uidState = AppOpsManager.extractUidStateFromKey(key);
+            final int flags = AppOpsManager.extractFlagsFromKey(key);
+
+            final long accessCount = op.getAccessCount(uidState, uidState, flags);
+            final long rejectCount = op.getRejectCount(uidState, uidState, flags);
+            final long accessDuration = op.getAccessDuration(uidState, uidState, flags);
+
+            if (accessCount <= 0 && rejectCount <= 0 && accessDuration <= 0) {
                 return;
             }
+
             serializer.startTag(null, TAG_STATE);
-            serializer.attribute(null, ATTR_NAME, Integer.toString(uidState));
+            serializer.attribute(null, ATTR_NAME, Long.toString(key));
             if (accessCount > 0) {
                 serializer.attribute(null, ATTR_ACCESS_COUNT, Long.toString(accessCount));
             }
@@ -1532,24 +1575,29 @@
             mWriter.print(mEntryPrefix);
             mWriter.print(AppOpsManager.opToName(ops.getOpCode()));
             mWriter.println(":");
-            for (int uidState = 0; uidState < AppOpsManager._NUM_UID_STATE; uidState++) {
+            final LongSparseArray keys = ops.collectKeys();
+            final int keyCount = keys.size();
+            for (int i = 0; i < keyCount; i++) {
+                final long key = keys.keyAt(i);
+                final int uidState = AppOpsManager.extractUidStateFromKey(key);
+                final int flags = AppOpsManager.extractFlagsFromKey(key);
                 boolean printedUidState = false;
-                final long accessCount = ops.getAccessCount(uidState);
+                final long accessCount = ops.getAccessCount(uidState, uidState, flags);
                 if (accessCount > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(AppOpsManager.keyToString(key));
                         mWriter.print(" = ");
                         printedUidState = true;
                     }
                     mWriter.print("access=");
                     mWriter.print(accessCount);
                 }
-                final long rejectCount = ops.getRejectCount(uidState);
+                final long rejectCount = ops.getRejectCount(uidState, uidState, flags);
                 if (rejectCount > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(AppOpsManager.keyToString(key));
                         mWriter.print(" = ");
                         printedUidState = true;
                     } else {
@@ -1558,11 +1606,11 @@
                     mWriter.print("reject=");
                     mWriter.print(rejectCount);
                 }
-                final long accessDuration = ops.getAccessDuration(uidState);
+                final long accessDuration = ops.getAccessDuration(uidState, uidState, flags);
                 if (accessDuration > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(AppOpsManager.keyToString(key));
                         mWriter.print(" = ");
                         printedUidState = true;
                     } else {
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
new file mode 100644
index 0000000..a53797d
--- /dev/null
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+    "presubmit": [
+        {
+            "name": "CtsAppOpsTestCases"
+        },
+        {
+            "name": "FrameworksServicesTests",
+            "options": [
+                {
+                    "include-filter": "com.android.server.appop"
+                }
+            ]
+        }
+    ]
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 9af57da..451fd66 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -201,51 +201,72 @@
         }
     }
 
-    /*package*/ int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+    private static final class BtDeviceConnectionInfo {
+        final @NonNull BluetoothDevice mDevice;
+        final @AudioService.BtProfileConnectionState int mState;
+        final int mProfile;
+        final boolean mSupprNoisy;
+        final int mVolume;
+
+        BtDeviceConnectionInfo(@NonNull BluetoothDevice device,
+                @AudioService.BtProfileConnectionState int state,
+                int profile, boolean suppressNoisyIntent, int vol) {
+            mDevice = device;
+            mState = state;
+            mProfile = profile;
+            mSupprNoisy = suppressNoisyIntent;
+            mVolume = vol;
+        }
+    }
+
+    /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             int profile, boolean suppressNoisyIntent, int a2dpVolume) {
-        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
-                "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state
-                        // only querying address as this is the only readily available field
-                        // on the device
-                        + " addr=" + device.getAddress()
-                        + " prof=" + profile + " supprNoisy=" + suppressNoisyIntent
-                        + " vol=" + a2dpVolume)).printLog(TAG));
-        synchronized (mDeviceStateLock) {
-            if (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
-                    new BtHelper.BluetoothA2dpDeviceInfo(device))) {
-                AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                        "A2DP connection state ignored"));
-                return 0;
-            }
-            return mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
-                    device, state, profile, suppressNoisyIntent,
-                    AudioSystem.DEVICE_NONE, a2dpVolume);
-        }
+        final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
+                suppressNoisyIntent, a2dpVolume);
+
+        // TODO add a check to try to remove unprocessed messages for the same device (the old
+        //      check didn't work), and  make sure it doesn't conflict with config change message
+        sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
     /*package*/ int handleBluetoothA2dpActiveDeviceChange(
             @NonNull BluetoothDevice device,
             @AudioService.BtProfileConnectionState int state, int profile,
             boolean suppressNoisyIntent, int a2dpVolume) {
+        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
+        //   of handleBluetoothA2dpDeviceConfigChange and
+        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
         synchronized (mDeviceStateLock) {
             return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
                     suppressNoisyIntent, a2dpVolume);
         }
     }
 
-    /*package*/ int setBluetoothHearingAidDeviceConnectionState(
+    private static final class HearingAidDeviceConnectionInfo {
+        final @NonNull BluetoothDevice mDevice;
+        final @AudioService.BtProfileConnectionState int mState;
+        final boolean mSupprNoisy;
+        final int mMusicDevice;
+        final @NonNull String mEventSource;
+
+        HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device,
+                @AudioService.BtProfileConnectionState int state,
+                boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
+            mDevice = device;
+            mState = state;
+            mSupprNoisy = suppressNoisyIntent;
+            mMusicDevice = musicDevice;
+            mEventSource = eventSource;
+        }
+    }
+
+    /*package*/ void postBluetoothHearingAidDeviceConnectionState(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) {
-        AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
-                "setHearingAidDeviceConnectionState state=" + state
-                        + " addr=" + device.getAddress()
-                        + " supprNoisy=" + suppressNoisyIntent
-                        + " src=" + eventSource)).printLog(TAG));
-        synchronized (mDeviceStateLock) {
-            return mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
-                    device, state, suppressNoisyIntent, musicDevice);
-        }
+        final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo(
+                device, state, suppressNoisyIntent, musicDevice, eventSource);
+        sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
     }
 
     // never called by system components
@@ -766,6 +787,35 @@
                         mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
                     }
                     break;
+                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: {
+                    final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
+                                    + " state=" + info.mState
+                                    // only querying address as this is the only readily available
+                                    // field on the device
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
+                                    + " vol=" + info.mVolume)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothA2dpDeviceConnectionState(
+                                info.mDevice, info.mState, info.mProfile, info.mSupprNoisy,
+                                AudioSystem.DEVICE_NONE, info.mVolume);
+                    }
+                } break;
+                case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: {
+                    final HearingAidDeviceConnectionInfo info =
+                            (HearingAidDeviceConnectionInfo) msg.obj;
+                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+                            "setHearingAidDeviceConnectionState state=" + info.mState
+                                    + " addr=" + info.mDevice.getAddress()
+                                    + " supprNoisy=" + info.mSupprNoisy
+                                    + " src=" + info.mEventSource)).printLog(TAG));
+                    synchronized (mDeviceStateLock) {
+                        mDeviceInventory.setBluetoothHearingAidDeviceConnectionState(
+                                info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
+                    }
+                } break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -809,6 +859,10 @@
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
+    // process external command to (dis)connect an A2DP device
+    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
+    // process external command to (dis)connect a hearing aid device
+    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
 
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -821,6 +875,8 @@
             case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
             case MSG_TOGGLE_HDMI:
             case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
+            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
+            case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
                 return true;
             default:
                 return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 37f0496..41a3c98 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -578,7 +578,7 @@
         return mCurAudioRoutes;
     }
 
-    /*package*/ int setBluetoothA2dpDeviceConnectionState(
+    /*package*/ void setBluetoothA2dpDeviceConnectionState(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
         int delay;
@@ -614,46 +614,50 @@
                         delay);
             }
         }
-        return delay;
     }
 
     /*package*/ int handleBluetoothA2dpActiveDeviceChange(
             @NonNull BluetoothDevice device,
             @AudioService.BtProfileConnectionState int state, int profile,
             boolean suppressNoisyIntent, int a2dpVolume) {
-        if (state == BluetoothProfile.STATE_DISCONNECTED) {
-            return setBluetoothA2dpDeviceConnectionState(device, state, profile,
-                    suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
-        }
-        // state == BluetoothProfile.STATE_CONNECTED
-        synchronized (mConnectedDevices) {
-            for (int i = 0; i < mConnectedDevices.size(); i++) {
-                final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
-                if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
-                    continue;
-                }
-                // If A2DP device exists, this is either an active device change or
-                // device config change
-                final String existingDevicekey = mConnectedDevices.keyAt(i);
-                final String deviceName = device.getName();
-                final String address = device.getAddress();
-                final String newDeviceKey = DeviceInfo.makeDeviceListKey(
-                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
-                int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
-                // Device not equal to existing device, active device change
-                if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
-                    mConnectedDevices.remove(existingDevicekey);
-                    mConnectedDevices.put(newDeviceKey, new DeviceInfo(
-                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
-                            address, a2dpCodec));
-                    mDeviceBroker.postA2dpActiveDeviceChange(
-                            new BtHelper.BluetoothA2dpDeviceInfo(
-                                    device, a2dpVolume, a2dpCodec));
-                    return 0;
-                } else {
-                    // Device config change for existing device
-                    mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
-                    return 0;
+        // method was added by QC but never used, and now conflicts with async behavior of
+        // handleBluetoothA2dpDeviceConfigChange and
+        // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
+        if (false) {
+            if (state == BluetoothProfile.STATE_DISCONNECTED) {
+                setBluetoothA2dpDeviceConnectionState(device, state, profile,
+                        suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
+            }
+            // state == BluetoothProfile.STATE_CONNECTED
+            synchronized (mConnectedDevices) {
+                for (int i = 0; i < mConnectedDevices.size(); i++) {
+                    final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
+                    if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+                        continue;
+                    }
+                    // If A2DP device exists, this is either an active device change or
+                    // device config change
+                    final String existingDevicekey = mConnectedDevices.keyAt(i);
+                    final String deviceName = device.getName();
+                    final String address = device.getAddress();
+                    final String newDeviceKey = DeviceInfo.makeDeviceListKey(
+                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
+                    int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
+                    // Device not equal to existing device, active device change
+                    if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
+                        mConnectedDevices.remove(existingDevicekey);
+                        mConnectedDevices.put(newDeviceKey, new DeviceInfo(
+                                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
+                                address, a2dpCodec));
+                        mDeviceBroker.postA2dpActiveDeviceChange(
+                                new BtHelper.BluetoothA2dpDeviceInfo(
+                                        device, a2dpVolume, a2dpCodec));
+                        return 0;
+                    } else {
+                        // Device config change for existing device
+                        mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
+                        return 0;
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6bd412b..91d19de 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4041,7 +4041,10 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface BtProfileConnectionState {}
 
-    public int setBluetoothHearingAidDeviceConnectionState(
+    /**
+     * See AudioManager.setBluetoothHearingAidDeviceConnectionState()
+     */
+    public void setBluetoothHearingAidDeviceConnectionState(
             @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
             boolean suppressNoisyIntent, int musicDevice)
     {
@@ -4053,14 +4056,14 @@
             throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
                     + " (dis)connection, got " + state);
         }
-        return mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
+        mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
                 device, state, suppressNoisyIntent, musicDevice, "AudioService");
     }
 
     /**
      * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
      */
-    public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+    public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             int profile, boolean suppressNoisyIntent, int a2dpVolume) {
         if (device == null) {
@@ -4071,7 +4074,7 @@
             throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
                     + " (dis)connection, got " + state);
         }
-        return mDeviceBroker.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
+        mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
                 profile, suppressNoisyIntent, a2dpVolume);
     }
 
@@ -4094,6 +4097,9 @@
     public int handleBluetoothA2dpActiveDeviceChange(
             BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
             int a2dpVolume) {
+        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
+        //   of handleBluetoothA2dpDeviceConfigChange and
+        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
         if (device == null) {
             throw new IllegalArgumentException("Illegal null device");
         }
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 58c1882..04073cb 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -426,7 +426,7 @@
         final BluetoothDevice btDevice = deviceList.get(0);
         final @BluetoothProfile.BtProfileState int state =
                 mHearingAid.getConnectionState(btDevice);
-        mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
+        mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
                 btDevice, state,
                 /*suppressNoisyIntent*/ false,
                 /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index d2d1482..feeb16b 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -32,6 +32,7 @@
 import android.hardware.biometrics.IBiometricServiceReceiverInternal;
 import android.hardware.biometrics.face.V1_0.IBiometricsFace;
 import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
+import android.hardware.biometrics.face.V1_0.OptionalBool;
 import android.hardware.biometrics.face.V1_0.Status;
 import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
@@ -54,7 +55,6 @@
 import com.android.server.biometrics.AuthenticationClient;
 import com.android.server.biometrics.BiometricServiceBase;
 import com.android.server.biometrics.BiometricUtils;
-import com.android.server.biometrics.ClientMonitor;
 import com.android.server.biometrics.EnumerateClient;
 import com.android.server.biometrics.Metrics;
 import com.android.server.biometrics.RemovalClient;
@@ -385,38 +385,61 @@
         }
 
         @Override
-        public int setFeature(int feature, boolean enabled, final byte[] token) {
+        public boolean setFeature(int feature, boolean enabled, final byte[] token) {
             checkPermission(MANAGE_BIOMETRIC);
 
+            if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
+                Slog.e(TAG, "No enrolled biometrics while setting feature: " + feature);
+                return false;
+            }
+
             final ArrayList<Byte> byteToken = new ArrayList<>();
             for (int i = 0; i < token.length; i++) {
                 byteToken.add(token[i]);
             }
 
-            int result;
-            try {
-                result = mDaemon != null ? mDaemon.setFeature(feature, enabled, byteToken)
-                        : Status.INTERNAL_ERROR;
-            } catch (RemoteException e) {
-                Slog.e(getTag(), "Unable to set feature: " + feature + " to enabled:" + enabled,
-                        e);
-                result = Status.INTERNAL_ERROR;
-            }
+            // TODO: Support multiple faces
+            final int faceId = getFirstTemplateForUser(mCurrentUserId);
 
-            return result;
+            if (mDaemon != null) {
+                try {
+                    return mDaemon.setFeature(feature, enabled, byteToken, faceId) == Status.OK;
+                } catch (RemoteException e) {
+                    Slog.e(getTag(), "Unable to set feature: " + feature + " to enabled:" + enabled,
+                            e);
+                }
+            }
+            return false;
         }
 
         @Override
         public boolean getFeature(int feature) {
             checkPermission(MANAGE_BIOMETRIC);
 
-            boolean result = true;
-            try {
-                result = mDaemon != null ? mDaemon.getFeature(feature) : true;
-            } catch (RemoteException e) {
-                Slog.e(getTag(), "Unable to getRequireAttention", e);
+            // This should ideally return tri-state, but the user isn't shown settings unless
+            // they are enrolled so it's fine for now.
+            if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
+                Slog.e(TAG, "No enrolled biometrics while getting feature: " + feature);
+                return false;
             }
-            return result;
+
+            // TODO: Support multiple faces
+            final int faceId = getFirstTemplateForUser(mCurrentUserId);
+
+            if (mDaemon != null) {
+                try {
+                    OptionalBool result = mDaemon.getFeature(feature, faceId);
+                    if (result.status == Status.OK) {
+                        return result.value;
+                    } else {
+                        // Same tri-state comment applies here.
+                        return false;
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(getTag(), "Unable to getRequireAttention", e);
+                }
+            }
+            return false;
         }
 
         @Override
@@ -431,6 +454,15 @@
                 }
             }
         }
+
+        // TODO: Support multiple faces
+        private int getFirstTemplateForUser(int user) {
+            final List<Face> faces = FaceService.this.getEnrolledTemplates(user);
+            if (!faces.isEmpty()) {
+                return faces.get(0).getBiometricId();
+            }
+            return 0;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 8a9ac23..65de83b 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -16,10 +16,12 @@
 package com.android.server.connectivity;
 
 import static android.net.SocketKeepalive.DATA_RECEIVED;
+import static android.net.SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
 import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
 import static android.net.SocketKeepalive.ERROR_SOCKET_NOT_IDLE;
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static android.system.OsConstants.ENOPROTOOPT;
 import static android.system.OsConstants.FIONREAD;
 import static android.system.OsConstants.IPPROTO_TCP;
 import static android.system.OsConstants.TIOCOUTQ;
@@ -179,12 +181,13 @@
             trw = NetworkUtils.getTcpRepairWindow(fd);
         } catch (ErrnoException e) {
             Log.e(TAG, "Exception reading TCP state from socket", e);
-            try {
-                Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
-            } catch (ErrnoException ex) {
-                Log.e(TAG, "Exception while turning off repair mode due to exception", ex);
+            if (e.errno == ENOPROTOOPT) {
+                // ENOPROTOOPT may happen in kernel version lower than 4.8.
+                // Treat it as ERROR_HARDWARE_UNSUPPORTED.
+                throw new InvalidSocketException(ERROR_HARDWARE_UNSUPPORTED, e);
+            } else {
+                throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
             }
-            throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
         } finally {
             dropAllIncomingPackets(fd, false);
         }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 13ff30d..3b4b6f8 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1677,10 +1677,10 @@
     }
 
     /** Get the latest value of the tethering entitlement check. */
-    public void getLatestTetheringEntitlementValue(int type, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver,
             boolean showEntitlementUi) {
         if (receiver != null) {
-            mEntitlementMgr.getLatestTetheringEntitlementValue(type, receiver, showEntitlementUi);
+            mEntitlementMgr.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
index 75aac10..65cc516 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -291,7 +291,7 @@
     }
 
     /** Get the last value of the tethering entitlement check. */
-    public void getLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
+    public void getLatestTetheringEntitlementResult(int downstream, ResultReceiver receiver,
             boolean showEntitlementUi) {
         if (!isTetherProvisioningRequired()) {
             receiver.send(TETHER_ERROR_NO_ERROR, null);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index e9ae516..9882f6c 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -138,9 +138,19 @@
     }
 
     /**
-     * Sets the mode, if supported.
+     * Sets the display modes the system is allowed to switch between, roughly ordered by
+     * preference.
+     *
+     * Not all display devices will automatically switch between modes, so it's important that the
+     * most-desired modes are at the beginning of the allowed array.
      */
-    public void requestDisplayModesLocked(int colorMode, int modeId) {
+    public void setAllowedDisplayModesLocked(int[] modes) {
+    }
+
+    /**
+     * Sets the requested color mode.
+     */
+    public void setRequestedColorModeLocked(int colorMode) {
     }
 
     public void onOverlayChangedLocked() {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 1aaaf41..32f34b8 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -167,13 +167,13 @@
     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
     private static final int MSG_REQUEST_TRAVERSAL = 4;
     private static final int MSG_UPDATE_VIEWPORT = 5;
-    private static final int MSG_REGISTER_BRIGHTNESS_TRACKER = 6;
-    private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 7;
+    private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 6;
 
     private final Context mContext;
     private final DisplayManagerHandler mHandler;
     private final Handler mUiHandler;
     private final DisplayAdapterListener mDisplayAdapterListener;
+    private final DisplayModeDirector mDisplayModeDirector;
     private WindowManagerInternal mWindowManagerInternal;
     private InputManagerInternal mInputManagerInternal;
     private IMediaProjectionManager mProjectionService;
@@ -310,6 +310,7 @@
         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
         mUiHandler = UiThread.getHandler();
         mDisplayAdapterListener = new DisplayAdapterListener();
+        mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
         Resources resources = mContext.getResources();
         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
@@ -322,7 +323,7 @@
         mMinimumBrightnessCurve = new Curve(lux, nits);
         mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
 
-        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        PowerManager pm = mContext.getSystemService(PowerManager.class);
         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
         mCurrentUserId = UserHandle.USER_SYSTEM;
         ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
@@ -347,9 +348,9 @@
         // adapter is up so that we have it's configuration. We could load it lazily, but since
         // we're going to have to read it in eventually we may as well do it here rather than after
         // we've waited for the display to register itself with us.
-		synchronized(mSyncRoot) {
-			mPersistentDataStore.loadIfNeeded();
-			loadStableDisplayValuesLocked();
+        synchronized (mSyncRoot) {
+            mPersistentDataStore.loadIfNeeded();
+            loadStableDisplayValuesLocked();
         }
         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
 
@@ -417,8 +418,10 @@
             mOnlyCore = onlyCore;
         }
 
+        mDisplayModeDirector.setListener(new AllowedDisplayModeObserver());
+        mDisplayModeDirector.start();
+
         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
-        mHandler.sendEmptyMessage(MSG_REGISTER_BRIGHTNESS_TRACKER);
     }
 
     @VisibleForTesting
@@ -1194,13 +1197,8 @@
                 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
                         requestedRefreshRate);
             }
-            if (display.getRequestedModeIdLocked() != requestedModeId) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
-                }
-                display.setRequestedModeIdLocked(requestedModeId);
-                scheduleTraversalLocked(inTraversal);
-            }
+            mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode(
+                    displayId, requestedModeId);
         }
     }
 
@@ -1319,6 +1317,28 @@
         return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
     }
 
+    private void onAllowedDisplayModesChangedInternal() {
+        boolean changed = false;
+        synchronized (mSyncRoot) {
+            final int count = mLogicalDisplays.size();
+            for (int i = 0; i < count; i++) {
+                LogicalDisplay display = mLogicalDisplays.valueAt(i);
+                int displayId = mLogicalDisplays.keyAt(i);
+                int[] allowedModes = mDisplayModeDirector.getAllowedModes(displayId);
+                // Note that order is important here since not all display devices are capable of
+                // automatically switching, so we do actually want to check for equality and not
+                // just equivalent contents (regardless of order).
+                if (!Arrays.equals(allowedModes, display.getAllowedDisplayModesLocked())) {
+                    display.setAllowedDisplayModesLocked(allowedModes);
+                    changed = true;
+                }
+            }
+            if (changed) {
+                scheduleTraversalLocked(false);
+            }
+        }
+    }
+
     private void clearViewportsLocked() {
         mViewports.clear();
     }
@@ -1518,6 +1538,9 @@
                 display.dumpLocked(ipw);
             }
 
+            pw.println();
+            mDisplayModeDirector.dump(pw);
+
             final int callbackCount = mCallbacks.size();
             pw.println();
             pw.println("Callbacks: size=" + callbackCount);
@@ -1689,8 +1712,9 @@
          * Returns information about the specified logical display.
          *
          * @param displayId The logical display id.
-         * @return The logical display info, or null if the display does not exist.  The
-         * returned object must be treated as immutable.
+         * @return The logical display info, return {@code null} if the display does not exist or
+         * the calling UID isn't present on the display.  The returned object must be treated as
+         * immutable.
          */
         @Override // Binder call
         public DisplayInfo getDisplayInfo(int displayId) {
@@ -1717,6 +1741,16 @@
             }
         }
 
+        @Override // Binder call
+        public boolean isUidPresentOnDisplay(int uid, int displayId) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return isUidPresentOnDisplayInternal(uid, displayId);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         /**
          * Returns the stable device display size, in pixels.
          */
@@ -2385,11 +2419,6 @@
         }
 
         @Override
-        public boolean isUidPresentOnDisplay(int uid, int displayId) {
-            return isUidPresentOnDisplayInternal(uid, displayId);
-        }
-
-        @Override
         public void persistBrightnessTrackerState() {
             synchronized (mSyncRoot) {
                 mDisplayPowerController.persistBrightnessTrackerState();
@@ -2425,4 +2454,10 @@
         }
 
     }
+
+    class AllowedDisplayModeObserver implements DisplayModeDirector.Listener {
+        public void onAllowedDisplayModesChanged() {
+            onAllowedDisplayModesChangedInternal();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
new file mode 100644
index 0000000..af4db07
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -0,0 +1,685 @@
+/*
+ * 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.display;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import com.android.internal.R;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * The DisplayModeDirector is responsible for determining what modes are allowed to be
+ * automatically picked by the system based on system-wide and display-specific configuration.
+ */
+public class DisplayModeDirector {
+    private static final String TAG = "DisplayModeDirector";
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_ALLOWED_MODES_CHANGED = 1;
+
+    // Special ID used to indicate that given vote is to be applied globally, rather than to a
+    // specific display.
+    private static final int GLOBAL_ID = -1;
+
+    // What we consider to be the system's "default" refresh rate.
+    private static final float DEFAULT_REFRESH_RATE = 60f;
+
+    // The tolerance within which we consider something approximately equals.
+    private static final float EPSILON = 0.001f;
+
+    private final Object mLock = new Object();
+    private final Context mContext;
+
+    private final DisplayModeDirectorHandler mHandler;
+
+    // A map from the display ID to the collection of votes and their priority. The latter takes
+    // the form of another map from the priority to the vote itself so that each priority is
+    // guaranteed to have exactly one vote, which is also easily and efficiently replaceable.
+    private final SparseArray<SparseArray<Vote>> mVotesByDisplay;
+    // A map from the display ID to the supported modes on that display.
+    private final SparseArray<Display.Mode[]> mSupportedModesByDisplay;
+    // A map from the display ID to the default mode of that display.
+    private final SparseArray<Display.Mode> mDefaultModeByDisplay;
+
+    private final AppRequestObserver mAppRequestObserver;
+    private final SettingsObserver mSettingsObserver;
+    private final DisplayObserver mDisplayObserver;
+
+
+    private Listener mListener;
+
+    public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
+        mContext = context;
+        mHandler = new DisplayModeDirectorHandler(handler.getLooper());
+        mVotesByDisplay = new SparseArray<>();
+        mSupportedModesByDisplay = new SparseArray<>();
+        mDefaultModeByDisplay =  new SparseArray<>();
+        mAppRequestObserver = new AppRequestObserver();
+        mSettingsObserver = new SettingsObserver(context, handler);
+        mDisplayObserver = new DisplayObserver(context, handler);
+    }
+
+    /**
+     * Tells the DisplayModeDirector to update allowed votes and begin observing relevant system
+     * state.
+     *
+     * This has to be deferred because the object may be constructed before the rest of the system
+     * is ready.
+     */
+    public void start() {
+        mSettingsObserver.observe();
+        mDisplayObserver.observe();
+        mSettingsObserver.observe();
+        synchronized (mLock) {
+            // We may have a listener already registered before the call to start, so go ahead and
+            // notify them to pick up our newly initialized state.
+            notifyAllowedModesChangedLocked();
+        }
+    }
+
+    /**
+     * Calculates the modes the system is allowed to freely switch between based on global and
+     * display-specific constraints.
+     *
+     * @param displayId The display to query for.
+     * @return The IDs of the modes the system is allowed to freely switch between.
+     */
+    @NonNull
+    public int[] getAllowedModes(int displayId) {
+        synchronized (mLock) {
+            SparseArray<Vote> votes = getVotesLocked(displayId);
+            Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
+            Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId);
+            if (modes == null || defaultMode == null) {
+                Slog.e(TAG, "Asked about unknown display, returning empty allowed set! (id="
+                        + displayId + ")");
+                return new int[0];
+            }
+            return getAllowedModesLocked(votes, modes, defaultMode);
+        }
+    }
+
+    @NonNull
+    private SparseArray<Vote> getVotesLocked(int displayId) {
+        SparseArray<Vote> displayVotes = mVotesByDisplay.get(displayId);
+        final SparseArray<Vote> votes;
+        if (displayVotes != null) {
+            votes = displayVotes.clone();
+        } else {
+            votes = new SparseArray<>();
+        }
+
+        SparseArray<Vote> globalVotes = mVotesByDisplay.get(GLOBAL_ID);
+        if (globalVotes != null) {
+            for (int i = 0; i < globalVotes.size(); i++) {
+                int priority = globalVotes.keyAt(i);
+                if (votes.indexOfKey(priority) < 0) {
+                    votes.put(priority, globalVotes.valueAt(i));
+                }
+            }
+        }
+        return votes;
+    }
+
+    @NonNull
+    private int[] getAllowedModesLocked(@NonNull SparseArray<Vote> votes,
+            @NonNull Display.Mode[] modes, @NonNull Display.Mode defaultMode) {
+        int lowestConsideredPriority = Vote.MIN_PRIORITY;
+        while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
+            float minRefreshRate = 0f;
+            float maxRefreshRate = Float.POSITIVE_INFINITY;
+            int height = Vote.INVALID_SIZE;
+            int width = Vote.INVALID_SIZE;
+
+            for (int priority = Vote.MAX_PRIORITY;
+                    priority >= lowestConsideredPriority;
+                    priority--) {
+                Vote vote = votes.get(priority);
+                if (vote == null) {
+                    continue;
+                }
+                // For refresh rates, just use the tightest bounds of all the votes
+                minRefreshRate = Math.max(minRefreshRate, vote.minRefreshRate);
+                maxRefreshRate = Math.min(maxRefreshRate, vote.maxRefreshRate);
+                // For display size, use only the first vote we come across (i.e. the highest
+                // priority vote that includes the width / height).
+                if (height == Vote.INVALID_SIZE && width == Vote.INVALID_SIZE
+                        && vote.height > 0 && vote.width > 0) {
+                    width = vote.width;
+                    height = vote.height;
+                }
+            }
+
+            // If we don't have anything specifying the width / height of the display, just use the
+            // default width and height. We don't want these switching out from underneath us since
+            // it's a pretty disruptive behavior.
+            if (height == Vote.INVALID_SIZE || width == Vote.INVALID_SIZE) {
+                width = defaultMode.getPhysicalWidth();
+                height = defaultMode.getPhysicalHeight();
+            }
+
+            int[] availableModes =
+                    filterModes(modes, width, height, minRefreshRate, maxRefreshRate);
+            if (availableModes.length > 0) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
+                            + " with lowest priority considered "
+                            + Vote.priorityToString(lowestConsideredPriority)
+                            + " and constraints: "
+                            + "width=" + width
+                            + ", height=" + height
+                            + ", minRefreshRate=" + minRefreshRate
+                            + ", maxRefreshRate=" + maxRefreshRate);
+                }
+                return availableModes;
+            }
+
+            if (DEBUG) {
+                Slog.w(TAG, "Couldn't find available modes with lowest priority set to "
+                        + Vote.priorityToString(lowestConsideredPriority)
+                        + " and with the following constraints: "
+                        + "width=" + width
+                        + ", height=" + height
+                        + ", minRefreshRate=" + minRefreshRate
+                        + ", maxRefreshRate=" + maxRefreshRate);
+            }
+            // If we haven't found anything with the current set of votes, drop the current lowest
+            // priority vote.
+            lowestConsideredPriority++;
+        }
+
+        // If we still haven't found anything that matches our current set of votes, just fall back
+        // to the default mode.
+        return new int[] { defaultMode.getModeId() };
+    }
+
+    private int[] filterModes(Display.Mode[] supportedModes,
+            int width, int height, float minRefreshRate, float maxRefreshRate) {
+        ArrayList<Display.Mode> availableModes = new ArrayList<>();
+        for (Display.Mode mode : supportedModes) {
+            if (mode.getPhysicalWidth() != width || mode.getPhysicalHeight() != height) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Discarding mode " + mode.getModeId() + ", wrong size"
+                            + ": desiredWidth=" + width
+                            + ": desiredHeight=" + height
+                            + ": actualWidth=" + mode.getPhysicalWidth()
+                            + ": actualHeight=" + mode.getPhysicalHeight());
+                }
+                continue;
+            }
+            final float refreshRate = mode.getRefreshRate();
+            // Some refresh rates are calculated based on frame timings, so they aren't *exactly*
+            // equal to expected refresh rate. Given that, we apply a bit of tolerance to this
+            // comparison.
+            if (refreshRate < (minRefreshRate - EPSILON)
+                    || refreshRate > (maxRefreshRate + EPSILON)) {
+                if (DEBUG) {
+                    Slog.w(TAG, "Discarding mode " + mode.getModeId()
+                            + ", outside refresh rate bounds"
+                            + ": minRefreshRate=" + minRefreshRate
+                            + ", maxRefreshRate=" + maxRefreshRate
+                            + ", modeRefreshRate=" + refreshRate);
+                }
+                continue;
+            }
+            availableModes.add(mode);
+        }
+        final int size = availableModes.size();
+        int[] availableModeIds = new int[size];
+        for (int i = 0; i < size; i++) {
+            availableModeIds[i] = availableModes.get(i).getModeId();
+        }
+        return availableModeIds;
+    }
+
+    /**
+     * Gets the observer responsible for application display mode requests.
+     */
+    @NonNull
+    public AppRequestObserver getAppRequestObserver() {
+        // We don't need to lock here because mAppRequestObserver is a final field, which is
+        // guaranteed to be visible on all threads after construction.
+        return mAppRequestObserver;
+    }
+
+    /**
+     * Sets the listener for changes to allowed display modes.
+     */
+    public void setListener(@Nullable Listener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+    }
+
+    /**
+     * Print the object's state and debug information into the given stream.
+     *
+     * @param pw The stream to dump information to.
+     */
+    public void dump(PrintWriter pw) {
+        pw.println("DisplayModeDirector");
+        synchronized (mLock) {
+            pw.println("  mSupportedModesByDisplay:");
+            for (int i = 0; i < mSupportedModesByDisplay.size(); i++) {
+                final int id = mSupportedModesByDisplay.keyAt(i);
+                final Display.Mode[] modes = mSupportedModesByDisplay.valueAt(i);
+                pw.println("    " + id + " -> " + Arrays.toString(modes));
+            }
+            pw.println("  mDefaultModeByDisplay:");
+            for (int i = 0; i < mDefaultModeByDisplay.size(); i++) {
+                final int id = mDefaultModeByDisplay.keyAt(i);
+                final Display.Mode mode = mDefaultModeByDisplay.valueAt(i);
+                pw.println("    " + id + " -> " + mode);
+            }
+            pw.println("  mVotesByDisplay:");
+            for (int i = 0; i < mVotesByDisplay.size(); i++) {
+                pw.println("    " + mVotesByDisplay.keyAt(i) + ":");
+                SparseArray<Vote> votes = mVotesByDisplay.valueAt(i);
+                for (int p = Vote.MAX_PRIORITY; p >= Vote.MIN_PRIORITY; p--) {
+                    Vote vote = votes.get(p);
+                    if (vote == null) {
+                        continue;
+                    }
+                    pw.println("      " + Vote.priorityToString(p) + " -> " + vote);
+                }
+            }
+            mSettingsObserver.dumpLocked(pw);
+            mAppRequestObserver.dumpLocked(pw);
+        }
+    }
+
+    private void updateVoteLocked(int priority, Vote vote) {
+        updateVoteLocked(GLOBAL_ID, priority, vote);
+    }
+
+    private void updateVoteLocked(int displayId, int priority, Vote vote) {
+        if (DEBUG) {
+            Slog.i(TAG, "updateVoteLocked(displayId=" + displayId
+                    + ", priority=" + Vote.priorityToString(priority)
+                    + ", vote=" + vote + ")");
+        }
+        if (priority < Vote.MIN_PRIORITY || priority > Vote.MAX_PRIORITY) {
+            Slog.w(TAG, "Received a vote with an invalid priority, ignoring:"
+                    + " priority=" + Vote.priorityToString(priority)
+                    + ", vote=" + vote, new Throwable());
+            return;
+        }
+        final SparseArray<Vote> votes = getOrCreateVotesByDisplay(displayId);
+
+        Vote currentVote = votes.get(priority);
+        if (vote != null) {
+            votes.put(priority, vote);
+        } else {
+            votes.remove(priority);
+        }
+
+        if (votes.size() == 0) {
+            if (DEBUG) {
+                Slog.i(TAG, "No votes left for display " + displayId + ", removing.");
+            }
+            mVotesByDisplay.remove(displayId);
+        }
+
+        notifyAllowedModesChangedLocked();
+    }
+
+    private void notifyAllowedModesChangedLocked() {
+        if (mListener != null && !mHandler.hasMessages(MSG_ALLOWED_MODES_CHANGED)) {
+            // We need to post this to a handler to avoid calling out while holding the lock
+            // since we know there are things that both listen for changes as well as provide
+            // information. If we did call out while holding the lock, then there's no guaranteed
+            // lock order and we run the real of risk deadlock.
+            Message msg = mHandler.obtainMessage(MSG_ALLOWED_MODES_CHANGED, mListener);
+            msg.sendToTarget();
+        }
+    }
+
+    private SparseArray<Vote> getOrCreateVotesByDisplay(int displayId) {
+        int index = mVotesByDisplay.indexOfKey(displayId);
+        if (mVotesByDisplay.indexOfKey(displayId) >= 0) {
+            return mVotesByDisplay.get(displayId);
+        } else {
+            SparseArray<Vote> votes = new SparseArray<>();
+            mVotesByDisplay.put(displayId, votes);
+            return votes;
+        }
+    }
+
+    /**
+     * Listens for changes to display mode coordination.
+     */
+    public interface Listener {
+        /**
+         * Called when the allowed display modes may have changed.
+         */
+        void onAllowedDisplayModesChanged();
+    }
+
+    private static final class DisplayModeDirectorHandler extends Handler {
+        DisplayModeDirectorHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ALLOWED_MODES_CHANGED:
+                    Listener listener = (Listener) msg.obj;
+                    listener.onAllowedDisplayModesChanged();
+                    break;
+            }
+        }
+    }
+
+    private static final class Vote {
+        public static final int PRIORITY_USER_SETTING = 0;
+        // We split the app request into two priorities in case we can satisfy one desire without
+        // the other.
+        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 1;
+        public static final int PRIORITY_APP_REQUEST_SIZE = 2;
+        public static final int PRIORITY_LOW_POWER_MODE = 3;
+
+        // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
+        // appropriate, as well as priorityToString.
+
+        public static final int MIN_PRIORITY = PRIORITY_USER_SETTING;
+        public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
+
+        /**
+         * A value signifying an invalid width or height in a vote.
+         */
+        public static final int INVALID_SIZE = -1;
+
+        /**
+         * The requested width of the display in pixels, or INVALID_SIZE;
+         */
+        public final int width;
+        /**
+         * The requested height of the display in pixels, or INVALID_SIZE;
+         */
+        public final int height;
+
+        /**
+         * The lowest desired refresh rate.
+         */
+        public final float minRefreshRate;
+        /**
+         * The highest desired refresh rate.
+         */
+        public final float maxRefreshRate;
+
+        public static Vote forRefreshRates(float minRefreshRate, float maxRefreshRate) {
+            return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate);
+        }
+
+        public static Vote forSize(int width, int height) {
+            return new Vote(width, height, 0f, Float.POSITIVE_INFINITY);
+        }
+
+        private Vote(int width, int height,
+                float minRefreshRate, float maxRefreshRate) {
+            this.width = width;
+            this.height = height;
+            this.minRefreshRate = minRefreshRate;
+            this.maxRefreshRate = maxRefreshRate;
+        }
+
+        public static String priorityToString(int priority) {
+            switch (priority) {
+                case PRIORITY_USER_SETTING:
+                    return "PRIORITY_USER_SETTING";
+                case PRIORITY_APP_REQUEST_REFRESH_RATE:
+                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
+                case PRIORITY_APP_REQUEST_SIZE:
+                    return "PRIORITY_APP_REQUEST_SIZE";
+                case PRIORITY_LOW_POWER_MODE:
+                    return "PRIORITY_LOW_POWER_MODE";
+                default:
+                    return Integer.toString(priority);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "Vote{"
+                + "width=" + width
+                + ", height=" + height
+                + ", minRefreshRate=" + minRefreshRate
+                + ", maxRefreshRate=" + maxRefreshRate
+                + "}";
+        }
+    }
+
+    private final class SettingsObserver extends ContentObserver {
+        private final Uri mRefreshRateSetting =
+                Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
+        private final Uri mLowPowerModeSetting =
+                Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);
+
+        private final Context mContext;
+        private final float mDefaultPeakRefreshRate;
+
+        SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
+            super(handler);
+            mContext = context;
+            mDefaultPeakRefreshRate = (float) context.getResources().getInteger(
+                    R.integer.config_defaultPeakRefreshRate);
+        }
+
+        public void observe() {
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.registerContentObserver(mRefreshRateSetting, false /*notifyDescendants*/, this,
+                    UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
+                    UserHandle.USER_SYSTEM);
+            synchronized (mLock) {
+                updateRefreshRateSettingLocked();
+                updateLowPowerModeSettingLocked();
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            synchronized (mLock) {
+                if (mRefreshRateSetting.equals(uri)) {
+                    updateRefreshRateSettingLocked();
+                } else if (mLowPowerModeSetting.equals(uri)) {
+                    updateLowPowerModeSettingLocked();
+                }
+            }
+        }
+
+        private void updateLowPowerModeSettingLocked() {
+            boolean inLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0;
+            final Vote vote;
+            if (inLowPowerMode) {
+                vote = Vote.forRefreshRates(0f, 60f);
+            } else {
+                vote = null;
+            }
+            updateVoteLocked(Vote.PRIORITY_LOW_POWER_MODE, vote);
+        }
+
+        private void updateRefreshRateSettingLocked() {
+            float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
+                    Settings.System.PEAK_REFRESH_RATE, DEFAULT_REFRESH_RATE);
+            Vote vote = Vote.forRefreshRates(0f, peakRefreshRate);
+            updateVoteLocked(Vote.PRIORITY_USER_SETTING, vote);
+        }
+
+        public void dumpLocked(PrintWriter pw) {
+            pw.println("  SettingsObserver");
+            pw.println("    mDefaultPeakRefreshRate: " + mDefaultPeakRefreshRate);
+        }
+    }
+
+    final class AppRequestObserver {
+        private SparseArray<Display.Mode> mAppRequestedModeByDisplay;
+
+        AppRequestObserver() {
+            mAppRequestedModeByDisplay = new SparseArray<>();
+        }
+
+        public void setAppRequestedMode(int displayId, int modeId) {
+            synchronized (mLock) {
+                setAppRequestedModeLocked(displayId, modeId);
+            }
+        }
+
+        private void setAppRequestedModeLocked(int displayId, int modeId) {
+            final Display.Mode requestedMode = findModeByIdLocked(displayId, modeId);
+            if (Objects.equals(requestedMode, mAppRequestedModeByDisplay.get(displayId))) {
+                return;
+            }
+
+            final Vote refreshRateVote;
+            final Vote sizeVote;
+            if (requestedMode != null) {
+                mAppRequestedModeByDisplay.put(displayId, requestedMode);
+                float refreshRate = requestedMode.getRefreshRate();
+                refreshRateVote = Vote.forRefreshRates(refreshRate, refreshRate);
+                sizeVote = Vote.forSize(requestedMode.getPhysicalWidth(),
+                        requestedMode.getPhysicalHeight());
+            } else {
+                mAppRequestedModeByDisplay.remove(displayId);
+                refreshRateVote = null;
+                sizeVote = null;
+            }
+            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
+            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
+            return;
+        }
+
+        private Display.Mode findModeByIdLocked(int displayId, int modeId) {
+            Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
+            if (modes == null) {
+                return null;
+            }
+            for (Display.Mode mode : modes) {
+                if (mode.getModeId() == modeId) {
+                    return mode;
+                }
+            }
+            return null;
+        }
+
+        public void dumpLocked(PrintWriter pw) {
+            pw.println("  AppRequestObserver");
+            pw.println("    mAppRequestedModeByDisplay:");
+            for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
+                final int id = mAppRequestedModeByDisplay.keyAt(i);
+                final Display.Mode mode = mAppRequestedModeByDisplay.valueAt(i);
+                pw.println("    " + id + " -> " + mode);
+            }
+        }
+    }
+
+    private final class DisplayObserver implements DisplayManager.DisplayListener {
+        // Note that we can never call into DisplayManager or any of the non-POD classes it
+        // returns, while holding mLock since it may call into DMS, which might be simultaneously
+        // calling into us already holding its own lock.
+        private final Context mContext;
+        private final Handler mHandler;
+
+        DisplayObserver(Context context, Handler handler) {
+            mContext = context;
+            mHandler = handler;
+        }
+
+        public void observe() {
+            DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+            dm.registerDisplayListener(this, mHandler);
+
+            // Populate existing displays
+            SparseArray<Display.Mode[]> modes = new SparseArray<>();
+            SparseArray<Display.Mode> defaultModes = new SparseArray<>();
+            DisplayInfo info = new DisplayInfo();
+            Display[] displays = dm.getDisplays();
+            for (Display d : displays) {
+                final int displayId = d.getDisplayId();
+                d.getDisplayInfo(info);
+                modes.put(displayId, info.supportedModes);
+                defaultModes.put(displayId, info.getDefaultMode());
+            }
+            synchronized (mLock) {
+                final int size = modes.size();
+                for (int i = 0; i < size; i++) {
+                    mSupportedModesByDisplay.put(modes.keyAt(i), modes.valueAt(i));
+                    mDefaultModeByDisplay.put(defaultModes.keyAt(i), defaultModes.valueAt(i));
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            updateDisplayModes(displayId);
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            synchronized (mLock) {
+                mSupportedModesByDisplay.remove(displayId);
+                mDefaultModeByDisplay.remove(displayId);
+            }
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            updateDisplayModes(displayId);
+        }
+
+        private void updateDisplayModes(int displayId) {
+            Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
+            DisplayInfo info = new DisplayInfo();
+            d.getDisplayInfo(info);
+            boolean changed = false;
+            synchronized (mLock) {
+                if (!Arrays.equals(mSupportedModesByDisplay.get(displayId), info.supportedModes)) {
+                    mSupportedModesByDisplay.put(displayId, info.supportedModes);
+                    changed = true;
+                }
+                if (!Objects.equals(mDefaultModeByDisplay.get(displayId), info.getDefaultMode())) {
+                    changed = true;
+                    mDefaultModeByDisplay.put(displayId, info.getDefaultMode());
+                }
+                if (changed) {
+                    notifyAllowedModesChangedLocked();
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 77df10b..5e5ef26 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -112,16 +112,18 @@
                 activeColorMode = Display.COLOR_MODE_INVALID;
             }
             int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
+            int[] allowedConfigs = SurfaceControl.getAllowedDisplayConfigs(displayToken);
             LocalDisplayDevice device = mDevices.get(physicalDisplayId);
             if (device == null) {
                 // Display was added.
                 final boolean isInternal = mDevices.size() == 0;
                 device = new LocalDisplayDevice(displayToken, physicalDisplayId,
-                        configs, activeConfig, colorModes, activeColorMode, isInternal);
+                        configs, activeConfig, allowedConfigs, colorModes, activeColorMode,
+                        isInternal);
                 mDevices.put(physicalDisplayId, device);
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
             } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
-                        colorModes, activeColorMode)) {
+                        allowedConfigs, colorModes, activeColorMode)) {
                 // Display properties changed.
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
             }
@@ -167,26 +169,30 @@
         private boolean mHavePendingChanges;
         private int mState = Display.STATE_UNKNOWN;
         private int mBrightness = PowerManager.BRIGHTNESS_DEFAULT;
-        private int mActivePhysIndex;
         private int mDefaultModeId;
         private int mActiveModeId;
         private boolean mActiveModeInvalid;
+        private int[] mAllowedModeIds;
+        private boolean mAllowedModeIdsInvalid;
+        private int mActivePhysIndex;
+        private int[] mAllowedPhysIndexes;
         private int mActiveColorMode;
         private boolean mActiveColorModeInvalid;
         private Display.HdrCapabilities mHdrCapabilities;
         private boolean mSidekickActive;
         private SidekickInternal mSidekickInternal;
 
-        private  SurfaceControl.PhysicalDisplayInfo mDisplayInfos[];
+        private SurfaceControl.PhysicalDisplayInfo[] mDisplayInfos;
 
         LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
                 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
-                int[] colorModes, int activeColorMode, boolean isInternal) {
+                int[] allowedDisplayInfos, int[] colorModes, int activeColorMode,
+                boolean isInternal) {
             super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
             mPhysicalDisplayId = physicalDisplayId;
             mIsInternal = isInternal;
             updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
-                    colorModes, activeColorMode);
+                    allowedDisplayInfos, colorModes, activeColorMode);
             updateColorModesLocked(colorModes, activeColorMode);
             mSidekickInternal = LocalServices.getService(SidekickInternal.class);
             if (mIsInternal) {
@@ -205,9 +211,10 @@
 
         public boolean updatePhysicalDisplayInfoLocked(
                 SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
-                int[] colorModes, int activeColorMode) {
+                int[] allowedDisplayInfos, int[] colorModes, int activeColorMode) {
             mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
             mActivePhysIndex = activeDisplayInfo;
+            mAllowedPhysIndexes = Arrays.copyOf(allowedDisplayInfos, allowedDisplayInfos.length);
             // Build an updated list of all existing modes.
             ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
             boolean modesAdded = false;
@@ -246,8 +253,9 @@
                     break;
                 }
             }
-            // Check whether surface flinger spontaneously changed modes out from under us. Schedule
-            // traversals to ensure that the correct state is reapplied if necessary.
+
+            // Check whether surface flinger spontaneously changed modes out from under us.
+            // Schedule traversals to ensure that the correct state is reapplied if necessary.
             if (mActiveModeId != 0
                     && mActiveModeId != activeRecord.mMode.getModeId()) {
                 mActiveModeInvalid = true;
@@ -266,6 +274,7 @@
             for (DisplayModeRecord record : records) {
                 mSupportedModes.put(record.mMode.getModeId(), record);
             }
+
             // Update the default mode, if needed.
             if (findDisplayInfoIndexLocked(mDefaultModeId) < 0) {
                 if (mDefaultModeId != 0) {
@@ -274,6 +283,7 @@
                 }
                 mDefaultModeId = activeRecord.mMode.getModeId();
             }
+
             // Determine whether the active mode is still there.
             if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
                 if (mActiveModeId != 0) {
@@ -284,6 +294,21 @@
                 mActiveModeInvalid = true;
             }
 
+            // Determine what the currently allowed modes are
+            mAllowedModeIds = new int[] { mActiveModeId };
+            int[] allowedModeIds = new int[mAllowedPhysIndexes.length];
+            int size = 0;
+            for (int physIndex : mAllowedPhysIndexes) {
+                int modeId = findMatchingModeIdLocked(physIndex);
+                if (modeId > 0) {
+                    allowedModeIds[size++] = modeId;
+                }
+            }
+
+            // If this is different from our desired allowed modes, then mark our current set as
+            // invalid so we correct this on the next traversal.
+            mAllowedModeIdsInvalid = !Arrays.equals(allowedModeIds, mAllowedModeIds);
+
             // Schedule traversals so that we apply pending changes.
             sendTraversalRequestLocked();
             return true;
@@ -368,11 +393,7 @@
                 mInfo.height = phys.height;
                 mInfo.modeId = mActiveModeId;
                 mInfo.defaultModeId = mDefaultModeId;
-                mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
-                for (int i = 0; i < mSupportedModes.size(); i++) {
-                    DisplayModeRecord record = mSupportedModes.valueAt(i);
-                    mInfo.supportedModes[i] = record.mMode;
-                }
+                mInfo.supportedModes = getDisplayModes(mSupportedModes);
                 mInfo.colorMode = mActiveColorMode;
                 mInfo.supportedColorModes =
                         new int[mSupportedColorModes.size()];
@@ -593,44 +614,104 @@
         }
 
         @Override
-        public void requestDisplayModesLocked(int colorMode, int modeId) {
-            if (requestModeLocked(modeId) ||
-                    requestColorModeLocked(colorMode)) {
+        public void setRequestedColorModeLocked(int colorMode) {
+            if (requestColorModeLocked(colorMode)) {
                 updateDeviceInfoLocked();
             }
         }
 
         @Override
+        public void setAllowedDisplayModesLocked(int[] modes) {
+            updateAllowedModesLocked(modes);
+        }
+
+        @Override
         public void onOverlayChangedLocked() {
             updateDeviceInfoLocked();
         }
 
-        public boolean requestModeLocked(int modeId) {
-            if (modeId == 0) {
-                modeId = mDefaultModeId;
-            } else if (mSupportedModes.indexOfKey(modeId) < 0) {
-                Slog.w(TAG, "Requested mode " + modeId + " is not supported by this display,"
-                        + " reverting to default display mode.");
-                modeId = mDefaultModeId;
+        public void onActivePhysicalDisplayModeChangedLocked(int physIndex) {
+            if (updateActiveModeLocked(physIndex)) {
+                updateDeviceInfoLocked();
             }
+        }
 
-            int physIndex = findDisplayInfoIndexLocked(modeId);
-            if (physIndex < 0) {
-                Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
-                        + " trying with default mode ID");
-                modeId = mDefaultModeId;
-                physIndex = findDisplayInfoIndexLocked(modeId);
-            }
-            if (mActivePhysIndex == physIndex) {
+        public boolean updateActiveModeLocked(int activePhysIndex) {
+            if (mActivePhysIndex == activePhysIndex) {
                 return false;
             }
-            SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
-            mActivePhysIndex = physIndex;
-            mActiveModeId = modeId;
-            mActiveModeInvalid = false;
+            mActivePhysIndex = activePhysIndex;
+            mActiveModeId = findMatchingModeIdLocked(activePhysIndex);
+            mActiveModeInvalid = mActiveModeId == 0;
+            if (mActiveModeInvalid) {
+                Slog.w(TAG, "In unknown mode after setting allowed configs"
+                        + ": allowedPhysIndexes=" + mAllowedPhysIndexes
+                        + ", activePhysIndex=" + mActivePhysIndex);
+            }
             return true;
         }
 
+        public void updateAllowedModesLocked(int[] allowedModes) {
+            if (Arrays.equals(allowedModes, mAllowedModeIds) && !mAllowedModeIdsInvalid) {
+                return;
+            }
+            if (updateAllowedModesInternalLocked(allowedModes)) {
+                updateDeviceInfoLocked();
+            }
+        }
+
+        public boolean updateAllowedModesInternalLocked(int[] allowedModes) {
+            if (DEBUG) {
+                Slog.w(TAG, "updateAllowedModesInternalLocked(allowedModes="
+                        + Arrays.toString(allowedModes) + ")");
+            }
+            int[] allowedPhysIndexes = new int[allowedModes.length];
+            int size = 0;
+            for (int modeId : allowedModes) {
+                int physIndex = findDisplayInfoIndexLocked(modeId);
+                if (physIndex < 0) {
+                    Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
+                            + " dropping from allowed set.");
+                } else {
+                    allowedPhysIndexes[size++] = physIndex;
+                }
+            }
+
+            // If we couldn't find one or more of the suggested allowed modes then we need to
+            // shrink the array to its actual size.
+            if (size != allowedModes.length) {
+                allowedPhysIndexes = Arrays.copyOf(allowedPhysIndexes, size);
+            }
+
+            // If we found no suitable modes, then we try again with the default mode which we
+            // assume has a suitable physical config.
+            if (size == 0) {
+                if (DEBUG) {
+                    Slog.w(TAG, "No valid modes allowed, falling back to default mode (id="
+                            + mDefaultModeId + ")");
+                }
+                allowedModes = new int[] { mDefaultModeId };
+                allowedPhysIndexes = new int[] { findDisplayInfoIndexLocked(mDefaultModeId) };
+            }
+
+            mAllowedModeIds = allowedModes;
+            mAllowedModeIdsInvalid = false;
+
+            if (Arrays.equals(mAllowedPhysIndexes, allowedPhysIndexes)) {
+                return false;
+            }
+            mAllowedPhysIndexes = allowedPhysIndexes;
+
+            if (DEBUG) {
+                Slog.w(TAG, "Setting allowed physical configs: allowedPhysIndexes="
+                        + Arrays.toString(allowedPhysIndexes));
+            }
+
+            SurfaceControl.setAllowedDisplayConfigs(getDisplayTokenLocked(), allowedPhysIndexes);
+            int activePhysIndex = SurfaceControl.getActiveConfig(getDisplayTokenLocked());
+            return updateActiveModeLocked(activePhysIndex);
+        }
+
         public boolean requestColorModeLocked(int colorMode) {
             if (mActiveColorMode == colorMode) {
                 return false;
@@ -650,9 +731,13 @@
         public void dumpLocked(PrintWriter pw) {
             super.dumpLocked(pw);
             pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
+            pw.println("mAllowedPhysIndexes=" + Arrays.toString(mAllowedPhysIndexes));
+            pw.println("mAllowedModeIds=" + Arrays.toString(mAllowedModeIds));
+            pw.println("mAllowedModeIdsInvalid=" + mAllowedModeIdsInvalid);
             pw.println("mActivePhysIndex=" + mActivePhysIndex);
             pw.println("mActiveModeId=" + mActiveModeId);
             pw.println("mActiveColorMode=" + mActiveColorMode);
+            pw.println("mDefaultModeId=" + mDefaultModeId);
             pw.println("mState=" + Display.stateToString(mState));
             pw.println("mBrightness=" + mBrightness);
             pw.println("mBacklight=" + mBacklight);
@@ -687,10 +772,31 @@
             return -1;
         }
 
+        private int findMatchingModeIdLocked(int physIndex) {
+            SurfaceControl.PhysicalDisplayInfo info = mDisplayInfos[physIndex];
+            for (int i = 0; i < mSupportedModes.size(); i++) {
+                DisplayModeRecord record = mSupportedModes.valueAt(i);
+                if (record.hasMatchingMode(info)) {
+                    return record.mMode.getModeId();
+                }
+            }
+            return 0;
+        }
+
         private void updateDeviceInfoLocked() {
             mInfo = null;
             sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
         }
+
+        private Display.Mode[] getDisplayModes(SparseArray<DisplayModeRecord> records) {
+            final int size = records.size();
+            Display.Mode[] modes = new Display.Mode[size];
+            for (int i = 0; i < size; i++) {
+                DisplayModeRecord record = records.valueAt(i);
+                modes[i] = record.mMode;
+            }
+            return modes;
+        }
     }
 
     /** Supplies a context whose Resources apply runtime-overlays */
@@ -745,12 +851,23 @@
         }
 
         @Override
-        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int configId) {
+        public void onConfigChanged(long timestampNanos, long physicalDisplayId, int physIndex) {
             if (DEBUG) {
                 Slog.d(TAG, "onConfigChanged("
                         + "timestampNanos=" + timestampNanos
-                        + ", builtInDisplayId=" + physicalDisplayId
-                        + ", configId=" + configId + ")");
+                        + ", physicalDisplayId=" + physicalDisplayId
+                        + ", physIndex=" + physIndex + ")");
+            }
+            synchronized (getSyncRoot()) {
+                LocalDisplayDevice device = mDevices.get(physicalDisplayId);
+                if (device == null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Received config change for unhandled physical display: "
+                                + "physicalDisplayId=" + physicalDisplayId);
+                    }
+                    return;
+                }
+                device.onActivePhysicalDisplayModeChangedLocked(physIndex);
             }
         }
     }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 7ee8422..a7b9051 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -87,7 +87,7 @@
     // True if the logical display has unique content.
     private boolean mHasContent;
 
-    private int mRequestedModeId;
+    private int[] mAllowedDisplayModes = new int[0];
     private int mRequestedColorMode;
 
     // The display offsets to apply to the display projection.
@@ -301,6 +301,7 @@
             boolean maskCutout =
                     (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
             mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;
+            mBaseDisplayInfo.displayId = mDisplayId;
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
@@ -353,12 +354,14 @@
         // Set the layer stack.
         device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
 
-        // Set the color mode and mode.
+        // Set the color mode and allowed display mode.
         if (device == mPrimaryDisplayDevice) {
-            device.requestDisplayModesLocked(
-                    mRequestedColorMode, mRequestedModeId);
+            device.setAllowedDisplayModesLocked(mAllowedDisplayModes);
+            device.setRequestedColorModeLocked(mRequestedColorMode);
         } else {
-            device.requestDisplayModesLocked(0, 0);  // Revert to default.
+            // Reset to default for non primary displays
+            device.setAllowedDisplayModesLocked(new int[] {0});
+            device.setRequestedColorModeLocked(0);
         }
 
         // Only grab the display info now as it may have been changed based on the requests above.
@@ -462,17 +465,17 @@
     }
 
     /**
-     * Requests the given mode.
+     * Sets the display modes the system is free to switch between.
      */
-    public void setRequestedModeIdLocked(int modeId) {
-        mRequestedModeId = modeId;
+    public void setAllowedDisplayModesLocked(int[] modes) {
+        mAllowedDisplayModes = modes;
     }
 
     /**
-     * Returns the pending requested mode.
+     * Returns the display modes the system is free to switch between.
      */
-    public int getRequestedModeIdLocked() {
-        return mRequestedModeId;
+    public int[] getAllowedDisplayModesLocked() {
+        return mAllowedDisplayModes;
     }
 
     /**
@@ -531,7 +534,7 @@
         pw.println("mDisplayId=" + mDisplayId);
         pw.println("mLayerStack=" + mLayerStack);
         pw.println("mHasContent=" + mHasContent);
-        pw.println("mRequestedMode=" + mRequestedModeId);
+        pw.println("mAllowedDisplayModes=" + Arrays.toString(mAllowedDisplayModes));
         pw.println("mRequestedColorMode=" + mRequestedColorMode);
         pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
         pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 2f507d1..60cfbd0 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -16,9 +16,6 @@
 
 package com.android.server.display;
 
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.IndentingPrintWriter;
-
 import android.content.Context;
 import android.database.ContentObserver;
 import android.graphics.SurfaceTexture;
@@ -32,6 +29,9 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -315,7 +315,16 @@
         }
 
         @Override
-        public void requestDisplayModesLocked(int color, int id) {
+        public void setAllowedDisplayModesLocked(int[] modes) {
+            final int id;
+            if (modes.length > 0) {
+                // The allowed modes should be ordered by preference, so just use the first mode
+                // here.
+                id = modes[0];
+            } else {
+                // If we don't have any allowed modes, just use the default mode.
+                id = 0;
+            }
             int index = -1;
             if (id == 0) {
                 // Use the default.
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8e8477a..29030fa 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -601,12 +601,11 @@
         // while IO initialization and registration is delegated to our internal handler
         // this approach is just fine because events are posted to our handler anyway
         mGnssConfiguration = new GnssConfiguration(mContext);
-        sendMessage(INITIALIZE_HANDLER, 0, null);
-
-        // Create a GPS net-initiated handler.
+        // Create a GPS net-initiated handler (also needed by handleInitialize)
         mNIHandler = new GpsNetInitiatedHandler(context,
                 mNetInitiatedListener,
                 mSuplEsEnabled);
+        sendMessage(INITIALIZE_HANDLER, 0, null);
 
         mGnssStatusListenerHelper = new GnssStatusListenerHelper(mContext, mHandler) {
             @Override
@@ -1320,10 +1319,6 @@
                 mAlarmManager.cancel(mTimeoutIntent);
             }
 
-            // send an intent to notify that the GPS is receiving fixes.
-            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
-            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             updateStatus(LocationProvider.AVAILABLE);
         }
 
@@ -1355,11 +1350,6 @@
 
         if (wasNavigating != mNavigating) {
             mGnssStatusListenerHelper.onStatusChanged(mNavigating);
-
-            // send an intent to notify that the GPS has been enabled or disabled
-            Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
-            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
         }
     }
 
@@ -1439,10 +1429,6 @@
 
         if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
                 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
-            // send an intent to notify that the GPS is no longer receiving fixes.
-            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
-            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
-            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
         }
     }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index ee968c8..0bc46f1 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1973,8 +1973,7 @@
         } catch (RemoteException ex) {
             Slog.w(TAG, "unable to clear GK secure user id");
         }
-        UserInfo userInfo = mUserManager.getUserInfo(userId);
-        if (unknownUser || userInfo == null || userInfo.isManagedProfile()) {
+        if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
             removeKeystoreProfileKey(userId);
         }
     }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 47b9c27..1b14ce2 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -53,6 +53,7 @@
 import com.android.server.locksettings.recoverablekeystore.certificate.CertXml;
 import com.android.server.locksettings.recoverablekeystore.certificate.SigXml;
 import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
+import com.android.server.locksettings.recoverablekeystore.storage.CleanupManager;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
@@ -100,6 +101,7 @@
     private final PlatformKeyManager mPlatformKeyManager;
     private final ApplicationKeyStorage mApplicationKeyStorage;
     private final TestOnlyInsecureCertificateHelper mTestCertHelper;
+    private final CleanupManager mCleanupManager;
 
     /**
      * Returns a new or existing instance.
@@ -122,16 +124,24 @@
                 throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
             }
 
+            RecoverySnapshotStorage snapshotStorage =
+                    RecoverySnapshotStorage.newInstance();
+            CleanupManager cleanupManager = CleanupManager.getInstance(
+                    context.getApplicationContext(),
+                    snapshotStorage,
+                    db,
+                    applicationKeyStorage);
             mInstance = new RecoverableKeyStoreManager(
                     context.getApplicationContext(),
                     db,
                     new RecoverySessionStorage(),
                     Executors.newSingleThreadExecutor(),
-                    RecoverySnapshotStorage.newInstance(),
+                    snapshotStorage,
                     new RecoverySnapshotListenersStorage(),
                     platformKeyManager,
                     applicationKeyStorage,
-                    new TestOnlyInsecureCertificateHelper());
+                    new TestOnlyInsecureCertificateHelper(),
+                    cleanupManager);
         }
         return mInstance;
     }
@@ -146,7 +156,8 @@
             RecoverySnapshotListenersStorage listenersStorage,
             PlatformKeyManager platformKeyManager,
             ApplicationKeyStorage applicationKeyStorage,
-            TestOnlyInsecureCertificateHelper TestOnlyInsecureCertificateHelper) {
+            TestOnlyInsecureCertificateHelper testOnlyInsecureCertificateHelper,
+            CleanupManager cleanupManager) {
         mContext = context;
         mDatabase = recoverableKeyStoreDb;
         mRecoverySessionStorage = recoverySessionStorage;
@@ -155,8 +166,10 @@
         mSnapshotStorage = snapshotStorage;
         mPlatformKeyManager = platformKeyManager;
         mApplicationKeyStorage = applicationKeyStorage;
-        mTestCertHelper = TestOnlyInsecureCertificateHelper;
-
+        mTestCertHelper = testOnlyInsecureCertificateHelper;
+        mCleanupManager = cleanupManager;
+        // Clears data for removed users.
+        mCleanupManager.verifyKnownUsers();
         try {
             mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mDatabase);
         } catch (NoSuchAlgorithmException e) {
@@ -955,6 +968,9 @@
         mContext.enforceCallingOrSelfPermission(
                 Manifest.permission.RECOVER_KEYSTORE,
                 "Caller " + Binder.getCallingUid() + " doesn't have RecoverKeyStore permission.");
+        int userId = UserHandle.getCallingUserId();
+        int uid = Binder.getCallingUid();
+        mCleanupManager.registerRecoveryAgent(userId, uid);
     }
 
     private boolean publicKeysMatch(PublicKey publicKey, byte[] vaultParams) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/CleanupManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/CleanupManager.java
new file mode 100644
index 0000000..be35b50
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/CleanupManager.java
@@ -0,0 +1,178 @@
+/*
+ * 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.locksettings.recoverablekeystore.storage;
+
+import android.content.Context;
+import android.os.ServiceSpecificException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.locksettings.recoverablekeystore.WrappedKey;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Cleans up data when user is removed.
+ */
+public class CleanupManager {
+    private static final String TAG = "CleanupManager";
+
+    private final Context mContext;
+    private final UserManager mUserManager;
+    private final RecoverableKeyStoreDb mDatabase;
+    private final RecoverySnapshotStorage mSnapshotStorage;
+    private final ApplicationKeyStorage mApplicationKeyStorage;
+
+    // Serial number can not be changed at runtime.
+    private Map<Integer, Long> mSerialNumbers; // Always in sync with the database.
+
+    /**
+     * Creates a new instance of the class.
+     * IMPORTANT: {@code verifyKnownUsers} must be called before the first data access.
+     */
+    public static CleanupManager getInstance(
+            Context context,
+            RecoverySnapshotStorage snapshotStorage,
+            RecoverableKeyStoreDb recoverableKeyStoreDb,
+            ApplicationKeyStorage applicationKeyStorage) {
+        return new CleanupManager(
+                context,
+                snapshotStorage,
+                recoverableKeyStoreDb,
+                UserManager.get(context),
+                applicationKeyStorage);
+    }
+
+    @VisibleForTesting
+    CleanupManager(
+            Context context,
+            RecoverySnapshotStorage snapshotStorage,
+            RecoverableKeyStoreDb recoverableKeyStoreDb,
+            UserManager userManager,
+            ApplicationKeyStorage applicationKeyStorage) {
+        mContext = context;
+        mSnapshotStorage = snapshotStorage;
+        mDatabase = recoverableKeyStoreDb;
+        mUserManager = userManager;
+        mApplicationKeyStorage = applicationKeyStorage;
+    }
+
+    /**
+     * Registers recovery agent in the system, if necessary.
+     */
+    public synchronized void registerRecoveryAgent(int userId, int uid) {
+        if (mSerialNumbers == null) {
+            // Table was uninitialized.
+            verifyKnownUsers();
+        }
+        // uid is ignored since recovery agent is a system app.
+        Long storedSerialNumber =  mSerialNumbers.get(userId);
+        if (storedSerialNumber == null) {
+            storedSerialNumber = -1L;
+        }
+        if (storedSerialNumber != -1) {
+            // User was already registered.
+            return;
+        }
+        // User was added after {@code verifyAllUsers} call.
+        long currentSerialNumber = mUserManager.getSerialNumberForUser(UserHandle.of(userId));
+        if (currentSerialNumber != -1) {
+            storeUserSerialNumber(userId, currentSerialNumber);
+        }
+    }
+
+    /**
+     * Removes data if serial number for a user was changed.
+     */
+    public synchronized void verifyKnownUsers() {
+        mSerialNumbers =  mDatabase.getUserSerialNumbers();
+        List<Integer> deletedUserIds = new ArrayList<Integer>(){};
+        for (Map.Entry<Integer, Long> entry : mSerialNumbers.entrySet()) {
+            Integer userId = entry.getKey();
+            Long storedSerialNumber = entry.getValue();
+            if (storedSerialNumber == null) {
+                storedSerialNumber = -1L;
+            }
+            long currentSerialNumber = mUserManager.getSerialNumberForUser(UserHandle.of(userId));
+            if (currentSerialNumber == -1) {
+                // User was removed.
+                deletedUserIds.add(userId);
+                removeDataForUser(userId);
+            } else if (storedSerialNumber == -1) {
+                // User is detected for the first time
+                storeUserSerialNumber(userId, currentSerialNumber);
+            } else if (storedSerialNumber != currentSerialNumber) {
+                // User has unexpected serial number - delete data related to old serial number.
+                deletedUserIds.add(userId);
+                removeDataForUser(userId);
+                // Register new user.
+                storeUserSerialNumber(userId, currentSerialNumber);
+            }
+        }
+
+        for (Integer deletedUser : deletedUserIds) {
+            mSerialNumbers.remove(deletedUser);
+        }
+    }
+
+    private void storeUserSerialNumber(int userId, long userSerialNumber) {
+        Log.d(TAG, "Storing serial number for user " + userId + ".");
+        mSerialNumbers.put(userId, userSerialNumber);
+        mDatabase.setUserSerialNumber(userId, userSerialNumber);
+    }
+
+    /**
+     * Removes all data for given user, including
+     *
+     * <ul>
+     *     <li> Recovery snapshots for all agents belonging to the {@code userId}.
+     *     <li> Entries with data related to {@code userId} from the database.
+     * </ul>
+     */
+    private void removeDataForUser(int userId) {
+        Log.d(TAG, "Removing data for user " + userId + ".");
+        List<Integer> recoveryAgents = mDatabase.getRecoveryAgents(userId);
+        for (Integer uid : recoveryAgents) {
+            mSnapshotStorage.remove(uid);
+            removeAllKeysForRecoveryAgent(userId, uid);
+        }
+
+        mDatabase.removeUserFromAllTables(userId);
+    }
+
+    /**
+     * Removes keys from Android KeyStore for the recovery agent;
+     * Doesn't remove encrypted key material from the database.
+     */
+    private void removeAllKeysForRecoveryAgent(int userId, int uid) {
+        int generationId = mDatabase.getPlatformKeyGenerationId(userId);
+        Map<String, WrappedKey> allKeys = mDatabase.getAllKeys(userId, uid, generationId);
+        for (String alias : allKeys.keySet()) {
+            try {
+                // Delete KeyStore copy.
+                mApplicationKeyStorage.deleteEntry(userId, uid, alias);
+            } catch (ServiceSpecificException e) {
+                // Ignore errors during key removal.
+                Log.e(TAG, "Error while removing recoverable key " + alias + " : " + e);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index dffaffe..3f5ac8e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -24,6 +24,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.security.keystore.recovery.RecoveryController;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.server.locksettings.recoverablekeystore.TestOnlyInsecureCertificateHelper;
@@ -261,7 +262,7 @@
      *
      * @hide
      */
-    public Map<String, WrappedKey> getAllKeys(int userId, int recoveryAgentUid,
+    public @NonNull Map<String, WrappedKey> getAllKeys(int userId, int recoveryAgentUid,
             int platformKeyGenerationId) {
         SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
         String[] projection = {
@@ -337,6 +338,58 @@
     }
 
     /**
+     * Returns serial numbers associated with all known users.
+     * -1 is used for uninitialized serial numbers.
+     *
+     * See {@code UserHandle.getSerialNumberForUser}.
+     * @return Map from userId to serial numbers.
+     */
+    public @NonNull Map<Integer, Long> getUserSerialNumbers() {
+        SQLiteDatabase db = mKeyStoreDbHelper.getReadableDatabase();
+        String[] projection = {
+                UserMetadataEntry.COLUMN_NAME_USER_ID,
+                UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER};
+        String selection = null; // get all rows.
+        String[] selectionArguments = {};
+
+        try (
+            Cursor cursor = db.query(
+                UserMetadataEntry.TABLE_NAME,
+                projection,
+                selection,
+                selectionArguments,
+                /*groupBy=*/ null,
+                /*having=*/ null,
+                /*orderBy=*/ null)
+        ) {
+            Map<Integer, Long> serialNumbers = new ArrayMap<>();
+            while (cursor.moveToNext()) {
+                int userId = cursor.getInt(
+                        cursor.getColumnIndexOrThrow(UserMetadataEntry.COLUMN_NAME_USER_ID));
+                long serialNumber = cursor.getLong(cursor.getColumnIndexOrThrow(
+                        UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER));
+                serialNumbers.put(userId, serialNumber);
+            }
+            return serialNumbers;
+        }
+    }
+
+    /**
+     * Sets the {@code serialNumber} for the user {@code userId}.
+     *
+     * @return The primary key of the inserted row, or -1 if failed.
+     */
+    public long setUserSerialNumber(int userId, long serialNumber) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, userId);
+        values.put(UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER, serialNumber);
+        long result = db.replace(
+                UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values);
+        return result;
+    }
+
+    /**
      * Updates status of old keys to {@code RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE}.
      */
     public void invalidateKeysWithOldGenerationId(int userId, int newGenerationId) {
@@ -424,8 +477,7 @@
      */
     @Nullable
     public Long getRecoveryServiceCertSerial(int userId, int uid, @NonNull String rootAlias) {
-        return getLong(userId, uid, rootAlias,
-                RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL);
+        return getLong(userId, uid, rootAlias, RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL);
     }
 
     /**
@@ -441,7 +493,7 @@
      */
     public long setRecoveryServiceCertSerial(int userId, int uid, @NonNull String rootAlias,
             long serial) {
-        return setLong(userId, uid, rootAlias, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL,
+        return setLong(userId, uid, rootAlias, RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL,
                 serial);
     }
 
@@ -457,8 +509,7 @@
      */
     @Nullable
     public CertPath getRecoveryServiceCertPath(int userId, int uid, @NonNull String rootAlias) {
-        byte[] bytes = getBytes(userId, uid, rootAlias,
-                RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH);
+        byte[] bytes = getBytes(userId, uid, rootAlias, RootOfTrustEntry.COLUMN_NAME_CERT_PATH);
         if (bytes == null) {
             return null;
         }
@@ -489,7 +540,7 @@
         if (certPath.getCertificates().size() == 0) {
             throw new CertificateEncodingException("No certificate contained in the cert path.");
         }
-        return setBytes(userId, uid, rootAlias, RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH,
+        return setBytes(userId, uid, rootAlias, RootOfTrustEntry.COLUMN_NAME_CERT_PATH,
                 certPath.getEncoded(CERT_PATH_ENCODING));
     }
 
@@ -1189,6 +1240,63 @@
                 RootOfTrustEntry.TABLE_NAME, values, selection, selectionArguments);
     }
 
+    /**
+     * Removes all entries for given {@code userId}.
+     */
+    public void removeUserFromAllTables(int userId) {
+        removeUserFromKeysTable(userId);
+        removeUserFromUserMetadataTable(userId);
+        removeUserFromRecoveryServiceMetadataTable(userId);
+        removeUserFromRootOfTrustTable(userId);
+    }
+
+    /**
+     * Removes all entries for given userId from Keys table.
+     *
+     * @return {@code true} if deleted a row.
+     */
+    private boolean removeUserFromKeysTable(int userId) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        String selection = KeysEntry.COLUMN_NAME_USER_ID + " = ?";
+        String[] selectionArgs = {Integer.toString(userId)};
+        return db.delete(KeysEntry.TABLE_NAME, selection, selectionArgs) > 0;
+    }
+
+    /**
+     * Removes all entries for given userId from UserMetadata table.
+     *
+     * @return {@code true} if deleted a row.
+     */
+    private boolean removeUserFromUserMetadataTable(int userId) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        String selection = UserMetadataEntry.COLUMN_NAME_USER_ID + " = ?";
+        String[] selectionArgs = {Integer.toString(userId)};
+        return db.delete(UserMetadataEntry.TABLE_NAME, selection, selectionArgs) > 0;
+    }
+
+    /**
+     * Removes all entries for given userId from RecoveryServiceMetadata table.
+     *
+     * @return {@code true} if deleted a row.
+     */
+    private boolean removeUserFromRecoveryServiceMetadataTable(int userId) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        String selection = RecoveryServiceMetadataEntry.COLUMN_NAME_USER_ID + " = ?";
+        String[] selectionArgs = {Integer.toString(userId)};
+        return db.delete(RecoveryServiceMetadataEntry.TABLE_NAME, selection, selectionArgs) > 0;
+    }
+
+    /**
+     * Removes all entries for given userId from RootOfTrust table.
+     *
+     * @return {@code true} if deleted a row.
+     */
+    private boolean removeUserFromRootOfTrustTable(int userId) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        String selection = RootOfTrustEntry.COLUMN_NAME_USER_ID + " = ?";
+        String[] selectionArgs = {Integer.toString(userId)};
+        return db.delete(RootOfTrustEntry.TABLE_NAME, selection, selectionArgs) > 0;
+    }
 
     /**
      * Creates an empty row in the recovery service metadata table if such a row doesn't exist for
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
index b58ee4b..e79d117 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java
@@ -20,6 +20,8 @@
 
 /**
  * Contract for recoverable key database. Describes the tables present.
+ *
+ * Make sure that {@code removeUserFromAllKnownTables} is updated, when new table is added.
  */
 class RecoverableKeyStoreDbContract {
     /**
@@ -91,6 +93,11 @@
          * is used to wrap recoverable keys on disk.
          */
         static final String COLUMN_NAME_PLATFORM_KEY_GENERATION_ID = "platform_key_generation_id";
+
+        /**
+         * Serial number for the user which can not be reused. Default value is {@code -1}.
+         */
+        static final String COLUMN_NAME_USER_SERIAL_NUMBER = "user_serial_number";
     }
 
     /**
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
index b0613da..3e7b0a7 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java
@@ -32,7 +32,7 @@
 class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper {
     private static final String TAG = "RecoverableKeyStoreDbHp";
 
-    static final int DATABASE_VERSION = 5;
+    static final int DATABASE_VERSION = 6; // Added user id serial number.
     private static final String DATABASE_NAME = "recoverablekeystore.db";
 
     private static final String SQL_CREATE_KEYS_ENTRY =
@@ -54,7 +54,8 @@
             "CREATE TABLE " + UserMetadataEntry.TABLE_NAME + "( "
                     + UserMetadataEntry._ID + " INTEGER PRIMARY KEY,"
                     + UserMetadataEntry.COLUMN_NAME_USER_ID + " INTEGER UNIQUE,"
-                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER)";
+                    + UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID + " INTEGER,"
+                    + UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER + " INTEGER DEFAULT -1)";
 
     private static final String SQL_CREATE_RECOVERY_SERVICE_METADATA_ENTRY =
             "CREATE TABLE " + RecoveryServiceMetadataEntry.TABLE_NAME + " ("
@@ -79,7 +80,7 @@
                     + RootOfTrustEntry._ID + " INTEGER PRIMARY KEY,"
                     + RootOfTrustEntry.COLUMN_NAME_USER_ID + " INTEGER,"
                     + RootOfTrustEntry.COLUMN_NAME_UID + " INTEGER,"
-                    + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " TEST,"
+                    + RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS + " TEXT,"
                     + RootOfTrustEntry.COLUMN_NAME_CERT_PATH + " BLOB,"
                     + RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL + " INTEGER,"
                     + "UNIQUE("
@@ -141,6 +142,11 @@
             oldVersion = 5;
         }
 
+        if (oldVersion < 6 && newVersion >= 6) {
+            upgradeDbForVersion6(db);
+            oldVersion = 6;
+        }
+
         if (oldVersion != newVersion) {
             Log.e(TAG, "Failed to update recoverablekeystore database to the most recent version");
         }
@@ -179,6 +185,15 @@
                 KeysEntry.COLUMN_NAME_KEY_METADATA, "BLOB", /*defaultStr=*/ null);
     }
 
+    private void upgradeDbForVersion6(SQLiteDatabase db) {
+        Log.d(TAG, "Updating recoverable keystore database to version 6");
+        // adds a column to store the user serial number
+        addColumnToTable(db, UserMetadataEntry.TABLE_NAME,
+                UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER,
+                "INTEGER DEFAULT -1",
+                 /*defaultStr=*/ null);
+    }
+
     private static void addColumnToTable(
             SQLiteDatabase db, String tableName, String column, String columnType,
             String defaultStr) {
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 41f2cc5..64477a5 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -192,6 +192,11 @@
         return true;
     }
 
+    @Override
+    protected String getRequiredPermission() {
+        return null;
+    }
+
     public ManagedServiceInfo checkServiceToken(IConditionProvider provider) {
         synchronized(mMutex) {
             return checkServiceTokenLocked(provider);
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index cf09b8f..7a87a57 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -64,6 +64,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.TriPredicate;
 import com.android.server.notification.NotificationManagerService.DumpFilter;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -333,6 +334,7 @@
                         out.attribute(null, ATT_APPROVED_LIST, allowedItems);
                         out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId));
                         out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
+                        writeExtraAttributes(out, approvedUserId);
                         out.endTag(null, TAG_MANAGED_SERVICES);
 
                         if (!forBackup && isPrimary) {
@@ -345,17 +347,21 @@
                 }
             }
         }
-
         out.endTag(null, getConfig().xmlTag);
     }
 
+    /**
+     * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag.
+     */
+    protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {}
+
     protected void migrateToXml() {
         loadAllowedComponentsFromSettings();
     }
 
     public void readXml(
             XmlPullParser parser,
-            Predicate<String> allowedManagedServicePackages,
+            TriPredicate<String, Integer, String> allowedManagedServicePackages,
             boolean forRestore,
             int userId)
             throws XmlPullParserException, IOException {
@@ -377,9 +383,9 @@
                             ? userId : XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
                     final boolean isPrimary =
                             XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true);
-
-                    if (allowedManagedServicePackages == null ||
-                            allowedManagedServicePackages.test(getPackageName(approved))) {
+                    readExtraAttributes(tag, parser, resolvedUserId);
+                    if (allowedManagedServicePackages == null || allowedManagedServicePackages.test(
+                            getPackageName(approved), resolvedUserId, getRequiredPermission())) {
                         if (mUm.getUserInfo(resolvedUserId) != null) {
                             addApprovedList(approved, resolvedUserId, isPrimary);
                         }
@@ -391,6 +397,14 @@
         rebindServices(false, USER_ALL);
     }
 
+    /**
+     * Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag.
+     */
+    protected void readExtraAttributes(String tag, XmlPullParser parser, int userId)
+            throws IOException {}
+
+    protected abstract String getRequiredPermission();
+
     private void loadAllowedComponentsFromSettings() {
         for (UserInfo user : mUm.getUsers()) {
             final ContentResolver cr = mContext.getContentResolver();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e8c402c..9281bf8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -153,6 +153,7 @@
 import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.service.notification.Adjustment;
 import android.service.notification.Condition;
@@ -190,6 +191,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -203,6 +205,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.util.function.TriPredicate;
 import com.android.server.DeviceIdleController;
 import com.android.server.EventLogTags;
 import com.android.server.IoThread;
@@ -430,7 +433,7 @@
     private boolean mIsAutomotive;
 
     private MetricsLogger mMetricsLogger;
-    private Predicate<String> mAllowedManagedServicePackages;
+    private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
 
     private static class Archive {
         final int mBufferSize;
@@ -515,26 +518,32 @@
             }
         }
 
-        readDefaultAssistant(userId);
+        setDefaultAssistantForUser(userId);
     }
 
-    protected void readDefaultAssistant(int userId) {
-        String defaultAssistantAccess = getContext().getResources().getString(
-                com.android.internal.R.string.config_defaultAssistantAccessPackage);
-        if (defaultAssistantAccess != null) {
-            // Gather all notification assistant components for candidate pkg. There should
-            // only be one
-            Set<ComponentName> approvedAssistants =
-                    mAssistants.queryPackageForServices(defaultAssistantAccess,
-                            MATCH_DIRECT_BOOT_AWARE
-                                    | MATCH_DIRECT_BOOT_UNAWARE, userId);
-            for (ComponentName cn : approvedAssistants) {
-                try {
-                    getBinderService().setNotificationAssistantAccessGrantedForUser(
-                            cn, userId, true);
-                } catch (RemoteException e) {
-                    e.printStackTrace();
-                }
+    protected void setDefaultAssistantForUser(int userId) {
+        List<ComponentName> validAssistants = new ArrayList<>(
+                mAssistants.queryPackageForServices(
+                        null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId));
+
+        List<String> candidateStrs = new ArrayList<>();
+        candidateStrs.add(DeviceConfig.getProperty(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE));
+        candidateStrs.add(getContext().getResources().getString(
+                com.android.internal.R.string.config_defaultAssistantAccessComponent));
+
+        for (String candidateStr : candidateStrs) {
+            if (TextUtils.isEmpty(candidateStr)) {
+                continue;
+            }
+            ComponentName candidate = ComponentName.unflattenFromString(candidateStr);
+            if (candidate != null && validAssistants.contains(candidate)) {
+                setNotificationAssistantAccessGrantedForUserInternal(candidate, userId, true);
+                Slog.d(TAG, String.format("Set default NAS to be %s in %d", candidateStr, userId));
+                return;
+            } else {
+                Slog.w(TAG, "Invalid default NAS config is found: " + candidateStr);
             }
         }
     }
@@ -594,6 +603,8 @@
             mConditionProviders.migrateToXml();
             handleSavePolicyFile();
         }
+
+        mAssistants.resetDefaultAssistantsIfNecessary();
     }
 
     private void loadPolicyFile() {
@@ -1740,6 +1751,21 @@
         publishLocalService(NotificationManagerInternal.class, mInternalService);
     }
 
+    private void registerDeviceConfigChange() {
+        DeviceConfig.addOnPropertyChangedListener(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                getContext().getMainExecutor(),
+                (namespace, name, value) -> {
+                    if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
+                        return;
+                    }
+                    if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) {
+                        mAssistants.resetDefaultAssistantsIfNecessary();
+                    }
+                });
+    }
+
+
     private GroupHelper getGroupHelper() {
         mAutoGroupAtCount =
                 getContext().getResources().getInteger(R.integer.config_autoGroupAtCount);
@@ -1803,6 +1829,7 @@
             mListeners.onBootPhaseAppsCanStart();
             mAssistants.onBootPhaseAppsCanStart();
             mConditionProviders.onBootPhaseAppsCanStart();
+            registerDeviceConfigChange();
         }
     }
 
@@ -3588,7 +3615,8 @@
             checkCallerIsSystemOrShell();
             final long identity = Binder.clearCallingIdentity();
             try {
-                if (mAllowedManagedServicePackages.test(pkg)) {
+                if (mAllowedManagedServicePackages.test(
+                        pkg, userId, mConditionProviders.getRequiredPermission())) {
                     mConditionProviders.setPackageOrComponentEnabled(
                             pkg, userId, true, granted);
 
@@ -3733,19 +3761,20 @@
 
         @Override
         public void setNotificationAssistantAccessGranted(ComponentName assistant,
-                boolean granted) throws RemoteException {
+                boolean granted) {
             setNotificationAssistantAccessGrantedForUser(
                     assistant, getCallingUserHandle().getIdentifier(), granted);
         }
 
         @Override
         public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
-                boolean granted) throws RemoteException {
+                boolean granted) {
             Preconditions.checkNotNull(listener);
             checkCallerIsSystemOrShell();
             final long identity = Binder.clearCallingIdentity();
             try {
-                if (mAllowedManagedServicePackages.test(listener.getPackageName())) {
+                if (mAllowedManagedServicePackages.test(
+                        listener.getPackageName(), userId, mListeners.getRequiredPermission())) {
                     mConditionProviders.setPackageOrComponentEnabled(listener.flattenToString(),
                             userId, false, granted);
                     mListeners.setPackageOrComponentEnabled(listener.flattenToString(),
@@ -3766,32 +3795,12 @@
 
         @Override
         public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
-                int userId, boolean granted) throws RemoteException {
+                int userId, boolean granted) {
             checkCallerIsSystemOrShell();
-            if (assistant == null) {
-                ComponentName allowedAssistant = CollectionUtils.firstOrNull(
-                        mAssistants.getAllowedComponents(userId));
-                if (allowedAssistant != null) {
-                    setNotificationAssistantAccessGrantedForUser(allowedAssistant, userId, false);
-                }
-                return;
-            }
+            mAssistants.setUserSet(userId, true);
             final long identity = Binder.clearCallingIdentity();
             try {
-                if (mAllowedManagedServicePackages.test(assistant.getPackageName())) {
-                    mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
-                            userId, false, granted);
-                    mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(),
-                            userId, true, granted);
-
-                    getContext().sendBroadcastAsUser(new Intent(
-                            NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
-                                    .setPackage(assistant.getPackageName())
-                                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
-                            UserHandle.of(userId), null);
-
-                    handleSavePolicyFile();
-                }
+                setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -4004,6 +4013,35 @@
         }
     };
 
+    @VisibleForTesting
+    protected void setNotificationAssistantAccessGrantedForUserInternal(
+            ComponentName assistant, int userId, boolean granted) {
+        if (assistant == null) {
+            ComponentName allowedAssistant = CollectionUtils.firstOrNull(
+                    mAssistants.getAllowedComponents(userId));
+            if (allowedAssistant != null) {
+                setNotificationAssistantAccessGrantedForUserInternal(
+                        allowedAssistant, userId, false);
+            }
+            return;
+        }
+        if (mAllowedManagedServicePackages.test(assistant.getPackageName(), userId,
+                mAssistants.getRequiredPermission())) {
+            mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
+                    userId, false, granted);
+            mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(),
+                    userId, true, granted);
+
+            getContext().sendBroadcastAsUser(new Intent(
+                            NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
+                            .setPackage(assistant.getPackageName())
+                            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+                    UserHandle.of(userId), null);
+
+            handleSavePolicyFile();
+        }
+    }
+
     private void applyAdjustment(NotificationRecord r, Adjustment adjustment) {
         if (r == null) {
             return;
@@ -7050,7 +7088,7 @@
     }
 
     @VisibleForTesting
-    boolean canUseManagedServices(String pkg) {
+    boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
         boolean canUseManagedServices = !mActivityManager.isLowRamDevice()
                 || mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_WATCH);
 
@@ -7061,6 +7099,17 @@
             }
         }
 
+        if (requiredPermission != null) {
+            try {
+                if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
+                    != PackageManager.PERMISSION_GRANTED) {
+                    canUseManagedServices = false;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "can't talk to pm", e);
+            }
+        }
+
         return canUseManagedServices;
     }
 
@@ -7091,6 +7140,13 @@
     public class NotificationAssistants extends ManagedServices {
         static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
 
+        private static final String ATT_USER_SET = "user_set";
+
+        private final Object mLock = new Object();
+
+        @GuardedBy("mLock")
+        private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>();
+
         public NotificationAssistants(Context context, Object lock, UserProfiles up,
                 IPackageManager pm) {
             super(context, lock, up, pm);
@@ -7138,6 +7194,12 @@
             rebindServices(true, user);
         }
 
+        @Override
+        protected String getRequiredPermission() {
+            // only signature/privileged apps can be bound
+            return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE;
+        }
+
         protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) {
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
@@ -7157,6 +7219,30 @@
             }
         }
 
+        boolean hasUserSet(int userId) {
+            synchronized (mLock) {
+                return mUserSetMap.getOrDefault(userId, false);
+            }
+        }
+
+        void setUserSet(int userId, boolean set) {
+            synchronized (mLock) {
+                mUserSetMap.put(userId, set);
+            }
+        }
+
+        @Override
+        protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {
+            out.attribute(null, ATT_USER_SET, Boolean.toString(hasUserSet(userId)));
+        }
+
+        @Override
+        protected void readExtraAttributes(String tag, XmlPullParser parser, int userId)
+                throws IOException {
+            boolean userSet = XmlUtils.readBooleanAttribute(parser, ATT_USER_SET, false);
+            setUserSet(userId, userSet);
+        }
+
         private void notifySeen(final ManagedServiceInfo info,
                 final ArrayList<String> keys) {
             final INotificationListener assistant = (INotificationListener) info.service;
@@ -7314,13 +7400,13 @@
             return !getServices().isEmpty();
         }
 
-        protected void ensureAssistant() {
+        protected void resetDefaultAssistantsIfNecessary() {
             final List<UserInfo> activeUsers = mUm.getUsers(true);
             for (UserInfo userInfo : activeUsers) {
                 int userId = userInfo.getUserHandle().getIdentifier();
-                if (getAllowedPackages(userId).isEmpty()) {
+                if (!hasUserSet(userId)) {
                     Slog.d(TAG, "Approving default notification assistant for user " + userId);
-                    readDefaultAssistant(userId);
+                    setDefaultAssistantForUser(userId);
                 }
             }
         }
@@ -7334,16 +7420,24 @@
                 if (!allowedComponents.isEmpty()) {
                     ComponentName currentComponent = CollectionUtils.firstOrNull(allowedComponents);
                     if (currentComponent.flattenToString().equals(pkgOrComponent)) return;
-                    try {
-                        getBinderService().setNotificationAssistantAccessGrantedForUser(
-                                currentComponent, userId, false);
-                    } catch (RemoteException e) {
-                        e.rethrowFromSystemServer();
-                    }
+                    setNotificationAssistantAccessGrantedForUserInternal(
+                            currentComponent, userId, false);
                 }
             }
             super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled);
         }
+
+        @Override
+        public void dump(PrintWriter pw, DumpFilter filter) {
+            super.dump(pw, filter);
+            pw.println("    Has user set:");
+            synchronized (mLock) {
+                Set<Integer> userIds = mUserSetMap.keySet();
+                for (int userId : userIds) {
+                    pw.println("      userId=" + userId + " value=" + mUserSetMap.get(userId));
+                }
+            }
+        }
     }
 
     public class NotificationListeners extends ManagedServices {
@@ -7413,6 +7507,11 @@
             mLightTrimListeners.remove(removed);
         }
 
+        @Override
+        protected String getRequiredPermission() {
+            return null;
+        }
+
         @GuardedBy("mNotificationLock")
         public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
             if (trim == TRIM_LIGHT) {
@@ -7896,6 +7995,19 @@
     }
 
     @VisibleForTesting
+    void resetAssistantUserSet(int userId) {
+        mAssistants.setUserSet(userId, false);
+        handleSavePolicyFile();
+    }
+
+    @VisibleForTesting
+    @Nullable
+    ComponentName getApprovedAssistant(int userId) {
+        List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
+        return CollectionUtils.firstOrNull(allowedComponents);
+    }
+
+    @VisibleForTesting
     protected void simulatePackageSuspendBroadcast(boolean suspend, String pkg) {
         // only use for testing: mimic receive broadcast that package is (un)suspended
         // but does not actually (un)suspend the package
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 26cc0c1..dd0f420 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -58,6 +58,8 @@
             + "  disallow_dnd PACKAGE [user_id (current user if not specified)]\n"
             + "  suspend_package PACKAGE\n"
             + "  unsuspend_package PACKAGE\n"
+            + "  reset_assistant_user_set [user_id (current user if not specified)]\n"
+            + "  get_approved_assistant [user_id (current user if not specified)]\n"
             + "  post [--help | flags] TAG TEXT";
 
     private static final String NOTIFY_USAGE =
@@ -199,8 +201,29 @@
                     mDirectService.simulatePackageDistractionBroadcast(
                             Integer.parseInt(getNextArgRequired()),
                             getNextArgRequired().split(","));
+                    break;
                 }
-                break;
+                case "reset_assistant_user_set": {
+                    int userId = ActivityManager.getCurrentUser();
+                    if (peekNextArg() != null) {
+                        userId = Integer.parseInt(getNextArgRequired());
+                    }
+                    mDirectService.resetAssistantUserSet(userId);
+                    break;
+                }
+                case "get_approved_assistant": {
+                    int userId = ActivityManager.getCurrentUser();
+                    if (peekNextArg() != null) {
+                        userId = Integer.parseInt(getNextArgRequired());
+                    }
+                    ComponentName approvedAssistant = mDirectService.getApprovedAssistant(userId);
+                    if (approvedAssistant == null) {
+                        pw.println("null");
+                    } else {
+                        pw.println(approvedAssistant.flattenToString());
+                    }
+                    break;
+                }
                 case "post":
                 case "notify":
                     doNotify(pw);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 9e912843..05af13a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -744,12 +744,8 @@
             if (!canAccessProfile(user.getIdentifier(), "Cannot access usage limit")) {
                 return null;
             }
-
-            final PackageManagerInternal pmi =
-                    LocalServices.getService(PackageManagerInternal.class);
-            final ComponentName cn = pmi.getDefaultHomeActivity(user.getIdentifier());
-            if (!cn.getPackageName().equals(callingPackage)) {
-                throw new SecurityException("Caller is not the active launcher");
+            if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
+                throw new SecurityException("Caller is not the recents app");
             }
 
             final UsageStatsManagerInternal.AppUsageLimitData data =
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 8ce2568..3c1ee3e 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -14,72 +14,72 @@
 per-file StagingManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
 
 # dex
-per-file AbstractStatsBase.java = agampe@google.com
-per-file AbstractStatsBase.java = calin@google.com
-per-file AbstractStatsBase.java = ngeoffray@google.com
-per-file BackgroundDexOptService.java = agampe@google.com
-per-file BackgroundDexOptService.java = calin@google.com
-per-file BackgroundDexOptService.java = ngeoffray@google.com
-per-file CompilerStats.java = agampe@google.com
-per-file CompilerStats.java = calin@google.com
-per-file CompilerStats.java = ngeoffray@google.com
-per-file DynamicCodeLoggingService.java = agampe@google.com
-per-file DynamicCodeLoggingService.java = calin@google.com
-per-file DynamicCodeLoggingService.java = ngeoffray@google.com
-per-file InstructionSets.java = agampe@google.com
-per-file InstructionSets.java = calin@google.com
-per-file InstructionSets.java = ngeoffray@google.com
-per-file OtaDexoptService.java = agampe@google.com
-per-file OtaDexoptService.java = calin@google.com
-per-file OtaDexoptService.java = ngeoffray@google.com
-per-file OtaDexoptShellCommand.java = agampe@google.com
-per-file OtaDexoptShellCommand.java = calin@google.com
-per-file OtaDexoptShellCommand.java = ngeoffray@google.com
-per-file PackageDexOptimizer.java = agampe@google.com
-per-file PackageDexOptimizer.java = calin@google.com
-per-file PackageDexOptimizer.java = ngeoffray@google.com
-per-file PackageManagerServiceCompilerMapping.java = agampe@google.com
-per-file PackageManagerServiceCompilerMapping.java = calin@google.com
-per-file PackageManagerServiceCompilerMapping.java = ngeoffray@google.com
-per-file PackageUsage.java = agampe@google.com
-per-file PackageUsage.java = calin@google.com
-per-file PackageUsage.java = ngeoffray@google.com
+per-file AbstractStatsBase.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file AbstractStatsBase.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file AbstractStatsBase.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file BackgroundDexOptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file BackgroundDexOptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file BackgroundDexOptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file CompilerStats.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file CompilerStats.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file CompilerStats.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file DynamicCodeLoggingService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file DynamicCodeLoggingService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file DynamicCodeLoggingService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file InstructionSets.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file InstructionSets.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file InstructionSets.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptShellCommand.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptShellCommand.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file OtaDexoptShellCommand.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageDexOptimizer.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageDexOptimizer.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageDexOptimizer.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageManagerServiceCompilerMapping.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageManagerServiceCompilerMapping.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageUsage.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageUsage.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
+per-file PackageUsage.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
 
 # multi user / cross profile
-per-file CrossProfileAppsServiceImpl.java = omakoto@google.com
-per-file CrossProfileAppsServiceImpl.java = yamasani@google.com
-per-file CrossProfileAppsService.java = omakoto@google.com
-per-file CrossProfileAppsService.java = yamasani@google.com
-per-file CrossProfileIntentFilter.java = omakoto@google.com
-per-file CrossProfileIntentFilter.java = yamasani@google.com
-per-file CrossProfileIntentResolver.java = omakoto@google.com
-per-file CrossProfileIntentResolver.java = yamasani@google.com
-per-file UserManagerService.java = omakoto@google.com
-per-file UserManagerService.java = yamasani@google.com
-per-file UserRestrictionsUtils.java = omakoto@google.com
-per-file UserRestrictionsUtils.java = yamasani@google.com
-per-file UserRestrictionsUtils.java = rubinxu@google.com
-per-file UserRestrictionsUtils.java = sandness@google.com
+per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileAppsServiceImpl.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileAppsService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileIntentFilter.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileIntentResolver.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file UserManagerService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file UserManagerService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file UserRestrictionsUtils.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file UserRestrictionsUtils.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
+per-file UserRestrictionsUtils.java = rubinxu@google.com, yamasani@google.com, hackbod@google.com
+per-file UserRestrictionsUtils.java = sandness@google.com, yamasani@google.com, hackbod@google.com
 
 # security
-per-file KeySetHandle.java = cbrubaker@google.com
-per-file KeySetManagerService.java = cbrubaker@google.com
-per-file PackageKeySetData.java = cbrubaker@google.com
-per-file PackageSignatures.java = cbrubaker@google.com
-per-file SELinuxMMAC.java = cbrubaker@google.com
+per-file KeySetHandle.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file KeySetManagerService.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file PackageKeySetData.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file PackageSignatures.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file SELinuxMMAC.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
 
 # shortcuts
-per-file LauncherAppsService.java = omakoto@google.com
-per-file ShareTargetInfo.java = omakoto@google.com
-per-file ShortcutBitmapSaver.java = omakoto@google.com
-per-file ShortcutDumpFiles.java = omakoto@google.com
-per-file ShortcutLauncher.java = omakoto@google.com
-per-file ShortcutNonPersistentUser.java = omakoto@google.com
-per-file ShortcutPackage.java = omakoto@google.com
-per-file ShortcutPackageInfo.java = omakoto@google.com
-per-file ShortcutPackageItem.java = omakoto@google.com
-per-file ShortcutParser.java = omakoto@google.com
-per-file ShortcutRequestPinProcessor.java = omakoto@google.com
-per-file ShortcutService.java = omakoto@google.com
-per-file ShortcutUser.java = omakoto@google.com
+per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index b72e836..a3b72fd 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -481,6 +481,12 @@
             }
         }
 
+        if (callingUid == Process.SYSTEM_UID) {
+            params.installFlags |= PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+        } else {
+            params.installFlags &= ~PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE;
+        }
+
         boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
         if (params.isStaged || isApex) {
             mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 15a00d5..b64b7c64 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14698,14 +14698,10 @@
                                 @Override
                                 public void onReceive(Context context, Intent intent) {
                                     // the duration to wait for rollback to be enabled, in millis
-                                    long rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT;
-                                    try {
-                                        rollbackTimeout = Long.valueOf(
-                                            DeviceConfig.getProperty(
-                                                DeviceConfig.Rollback.NAMESPACE,
-                                                DeviceConfig.Rollback.ENABLE_ROLLBACK_TIMEOUT));
-                                    } catch (NumberFormatException ignore) {
-                                    }
+                                    long rollbackTimeout = DeviceConfig.getLong(
+                                            DeviceConfig.Rollback.NAMESPACE,
+                                            DeviceConfig.Rollback.ENABLE_ROLLBACK_TIMEOUT,
+                                            DEFAULT_ENABLE_ROLLBACK_TIMEOUT);
                                     final Message msg = mHandler.obtainMessage(
                                             ENABLE_ROLLBACK_TIMEOUT);
                                     msg.arg1 = enableRollbackToken;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 3218c86..ff81ad5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -806,7 +806,7 @@
      */
     public static boolean isDowngradePermitted(int installFlags, int applicationFlags) {
         // If installed, the package will get access to data left on the device by its
-        // predecessor. As a security measure, this is permited only if this is not a
+        // predecessor. As a security measure, this is permitted only if this is not a
         // version downgrade or if the predecessor package is marked as debuggable and
         // a downgrade is explicitly requested.
         //
@@ -818,12 +818,21 @@
         // installFlags. This is because we aim to keep the behavior of debuggable
         // platform builds as close as possible to the behavior of non-debuggable
         // platform builds.
+        //
+        // In case of user builds, downgrade is permitted only for the system server initiated
+        // sessions. This is enforced by INSTALL_RESPECT_ALLOW_DOWNGRADE flag parameter.
         final boolean downgradeRequested =
                 (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
-        final boolean packageDebuggable =
-                (applicationFlags
-                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-        return (downgradeRequested) && ((Build.IS_DEBUGGABLE) || (packageDebuggable));
+        if (!downgradeRequested) {
+            return false;
+        }
+        final boolean isDebuggable =
+                Build.IS_DEBUGGABLE || ((applicationFlags
+                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+        if (isDebuggable) {
+            return true;
+        }
+        return (installFlags & PackageManager.INSTALL_RESPECT_ALLOW_DOWNGRADE) != 0;
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d9a5eb9..eced165 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.LocusId;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
@@ -1702,15 +1703,17 @@
             flags |= ShortcutInfo.FLAG_SHADOW;
         }
 
+        LocusId locusId = null; // LocusId is not  set on XML.
+
         return new ShortcutInfo(
-                userId, id, packageName, activityComponent, /* icon =*/ null,
+                userId, id, packageName, activityComponent, /* icon= */ null,
                 title, titleResId, titleResName, text, textResId, textResName,
                 disabledMessage, disabledMessageResId, disabledMessageResName,
                 categories,
                 intents.toArray(new Intent[intents.size()]),
                 rank, extras, lastChangedTimestamp, flags,
                 iconResId, iconResName, bitmapPath, disabledReason,
-                persons.toArray(new Person[persons.size()]));
+                persons.toArray(new Person[persons.size()]), locusId);
     }
 
     private static Intent parseIntent(XmlPullParser parser)
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 668fc88..f9c0db0 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -450,7 +450,8 @@
                 null, // icon res name
                 null, // bitmap path
                 disabledReason,
-                null /* persons */);
+                null /* persons */,
+                null /* locusId */);
     }
 
     private static String parseCategory(ShortcutService service, AttributeSet attrs) {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index f52f3a3..d3e1a05 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -531,17 +531,10 @@
     }
 
     private void updateRollbackLifetimeDurationInMillis() {
-        String strRollbackLifetimeInMillis = DeviceConfig.getProperty(
+        mRollbackLifetimeDurationInMillis = DeviceConfig.getLong(
                 DeviceConfig.Rollback.BOOT_NAMESPACE,
-                DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS);
-
-        try {
-            mRollbackLifetimeDurationInMillis = (strRollbackLifetimeInMillis == null)
-                    ? DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS
-                    : Long.parseLong(strRollbackLifetimeInMillis);
-        } catch (NumberFormatException e) {
-            mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
-        }
+                DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
+                DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS);
     }
 
     void onBootCompleted() {
@@ -599,6 +592,8 @@
                     }
                 }
             }
+
+            mPackageHealthObserver.onBootCompleted();
         });
     }
 
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index d24f217..9348806 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -26,6 +26,8 @@
 import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
+import android.os.Environment;
+import android.os.FileUtils;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.PowerManager;
@@ -39,6 +41,12 @@
 import com.android.server.PackageWatchdog.PackageHealthObserver;
 import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
 
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.List;
 
@@ -50,14 +58,19 @@
 public final class RollbackPackageHealthObserver implements PackageHealthObserver {
     private static final String TAG = "RollbackPackageHealthObserver";
     private static final String NAME = "rollback-observer";
-    private Context mContext;
-    private Handler mHandler;
+    private static final int INVALID_ROLLBACK_ID = -1;
+    private final Context mContext;
+    private final Handler mHandler;
+    private final File mLastStagedRollbackIdFile;
 
     RollbackPackageHealthObserver(Context context) {
         mContext = context;
         HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
         handlerThread.start();
         mHandler = handlerThread.getThreadHandler();
+        File dataDir = new File(Environment.getDataDirectory(), "rollback-observer");
+        dataDir.mkdirs();
+        mLastStagedRollbackIdFile = new File(dataDir, "last-staged-rollback-id");
         PackageWatchdog.getInstance(mContext).registerHealthObserver(this);
     }
 
@@ -112,15 +125,19 @@
                 int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
                         RollbackManager.STATUS_FAILURE);
                 if (status == RollbackManager.STATUS_SUCCESS) {
-                    StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
-                            StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
-                            moduleMetadataPackage.getPackageName(),
-                            moduleMetadataPackage.getVersionCode());
                     if (rollback.isStaged()) {
                         int rollbackId = rollback.getRollbackId();
                         BroadcastReceiver listener =
-                                listenForStagedSessionReady(rollbackManager, rollbackId);
-                        handleStagedSessionChange(rollbackManager, rollbackId, listener);
+                                listenForStagedSessionReady(rollbackManager, rollbackId,
+                                        moduleMetadataPackage);
+                        handleStagedSessionChange(rollbackManager, rollbackId, listener,
+                                moduleMetadataPackage);
+                    } else {
+                        StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+                                StatsLog
+                                .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+                                moduleMetadataPackage.getPackageName(),
+                                moduleMetadataPackage.getVersionCode());
                     }
                 } else {
                     StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
@@ -149,7 +166,73 @@
      * This may cause {@code packages} to be rolled back if they crash too freqeuntly.
      */
     public void startObservingHealth(List<String> packages, long durationMs) {
-        PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
+        PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs,
+                false /* withExplicitHealthCheck */);
+    }
+
+    /** Verifies the rollback state after a reboot. */
+    public void onBootCompleted() {
+        int rollbackId = popLastStagedRollbackId();
+        if (rollbackId == INVALID_ROLLBACK_ID) {
+            // No staged rollback before reboot
+            return;
+        }
+
+        RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
+        PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+        RollbackInfo rollback = null;
+        for (RollbackInfo info : rollbackManager.getRecentlyCommittedRollbacks()) {
+            if (rollbackId == info.getRollbackId()) {
+                rollback = info;
+                break;
+            }
+        }
+
+        if (rollback == null) {
+            Slog.e(TAG, "rollback info not found for last staged rollback: " + rollbackId);
+            return;
+        }
+
+        String moduleMetadataPackageName = getModuleMetadataPackageName();
+        if (moduleMetadataPackageName == null) {
+            // Only log mainline staged rollbacks
+            return;
+        }
+
+        // Use the version of the metadata package that was installed before
+        // we rolled back for logging purposes.
+        VersionedPackage moduleMetadataPackage = null;
+        for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
+            if (moduleMetadataPackageName.equals(packageRollback.getPackageName())) {
+                moduleMetadataPackage = packageRollback.getVersionRolledBackFrom();
+                break;
+            }
+        }
+
+        if (moduleMetadataPackage == null) {
+            // Only log mainline staged rollbacks
+            return;
+        }
+
+        int sessionId = rollback.getCommittedSessionId();
+        PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId);
+        if (sessionInfo == null) {
+            Slog.e(TAG, "On boot completed, could not load session id " + sessionId);
+            return;
+        }
+        if (sessionInfo.isStagedSessionApplied()) {
+            StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+                    StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+                    moduleMetadataPackage.getPackageName(),
+                    moduleMetadataPackage.getVersionCode());
+        } else if (sessionInfo.isStagedSessionReady()) {
+            // TODO: What do for staged session ready but not applied
+        } else {
+            StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+                    StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+                    moduleMetadataPackage.getPackageName(),
+                    moduleMetadataPackage.getVersionCode());
+        }
     }
 
     private Pair<RollbackInfo, Boolean> getAvailableRollback(RollbackManager rollbackManager,
@@ -174,12 +257,20 @@
         return null;
     }
 
-    private VersionedPackage getModuleMetadataPackage() {
+    private String getModuleMetadataPackageName() {
         String packageName = mContext.getResources().getString(
                 R.string.config_defaultModuleMetadataProvider);
         if (TextUtils.isEmpty(packageName)) {
             return null;
         }
+        return packageName;
+    }
+
+    private VersionedPackage getModuleMetadataPackage() {
+        String packageName = getModuleMetadataPackageName();
+        if (packageName == null) {
+            return null;
+        }
 
         try {
             return new VersionedPackage(packageName, mContext.getPackageManager().getPackageInfo(
@@ -191,12 +282,12 @@
     }
 
     private BroadcastReceiver listenForStagedSessionReady(RollbackManager rollbackManager,
-            int rollbackId) {
+            int rollbackId, VersionedPackage moduleMetadataPackage) {
         BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 handleStagedSessionChange(rollbackManager,
-                        rollbackId, this /* BroadcastReceiver */);
+                        rollbackId, this /* BroadcastReceiver */, moduleMetadataPackage);
             }
         };
         IntentFilter sessionUpdatedFilter =
@@ -206,7 +297,7 @@
     }
 
     private void handleStagedSessionChange(RollbackManager rollbackManager, int rollbackId,
-            BroadcastReceiver listener) {
+            BroadcastReceiver listener, VersionedPackage moduleMetadataPackage) {
         PackageInstaller packageInstaller =
                 mContext.getPackageManager().getPackageInstaller();
         List<RollbackInfo> recentRollbacks =
@@ -220,11 +311,52 @@
                         packageInstaller.getSessionInfo(sessionId);
                 if (sessionInfo.isStagedSessionReady()) {
                     mContext.unregisterReceiver(listener);
+                    saveLastStagedRollbackId(rollbackId);
+                    StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+                            StatsLog
+                            .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
+                            moduleMetadataPackage.getPackageName(),
+                            moduleMetadataPackage.getVersionCode());
                     mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
                 } else if (sessionInfo.isStagedSessionFailed()) {
+                    StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED,
+                            StatsLog
+                            .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+                            moduleMetadataPackage.getPackageName(),
+                            moduleMetadataPackage.getVersionCode());
                     mContext.unregisterReceiver(listener);
                 }
             }
         }
     }
+
+    private void saveLastStagedRollbackId(int stagedRollbackId) {
+        try {
+            FileOutputStream fos = new FileOutputStream(mLastStagedRollbackIdFile);
+            PrintWriter pw = new PrintWriter(fos);
+            pw.println(stagedRollbackId);
+            pw.flush();
+            FileUtils.sync(fos);
+            pw.close();
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to save last staged rollback id", e);
+            mLastStagedRollbackIdFile.delete();
+        }
+    }
+
+    private int popLastStagedRollbackId() {
+        int rollbackId = INVALID_ROLLBACK_ID;
+        if (!mLastStagedRollbackIdFile.exists()) {
+            return rollbackId;
+        }
+
+        try {
+            rollbackId = Integer.parseInt(
+                    IoUtils.readFileAsString(mLastStagedRollbackIdFile.getAbsolutePath()).trim());
+        } catch (IOException | NumberFormatException e) {
+            Slog.e(TAG, "Failed to retrieve last staged rollback id", e);
+        }
+        mLastStagedRollbackIdFile.delete();
+        return rollbackId;
+    }
 }
diff --git a/services/core/java/com/android/server/signedconfig/TEST_MAPPING b/services/core/java/com/android/server/signedconfig/TEST_MAPPING
new file mode 100644
index 0000000..88e068f
--- /dev/null
+++ b/services/core/java/com/android/server/signedconfig/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsSignedConfigHostTestCases"
+    }
+  ]
+}
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index ef77140..a5d291f 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -27,12 +27,8 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.service.textclassifier.IConversationActionsCallback;
-import android.service.textclassifier.ITextClassificationCallback;
+import android.service.textclassifier.ITextClassifierCallback;
 import android.service.textclassifier.ITextClassifierService;
-import android.service.textclassifier.ITextLanguageCallback;
-import android.service.textclassifier.ITextLinksCallback;
-import android.service.textclassifier.ITextSelectionCallback;
 import android.service.textclassifier.TextClassifierService;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -132,7 +128,7 @@
     @Override
     public void onSuggestSelection(
             TextClassificationSessionId sessionId,
-            TextSelection.Request request, ITextSelectionCallback callback)
+            TextSelection.Request request, ITextClassifierCallback callback)
             throws RemoteException {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(callback);
@@ -155,7 +151,7 @@
     @Override
     public void onClassifyText(
             TextClassificationSessionId sessionId,
-            TextClassification.Request request, ITextClassificationCallback callback)
+            TextClassification.Request request, ITextClassifierCallback callback)
             throws RemoteException {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(callback);
@@ -178,7 +174,7 @@
     @Override
     public void onGenerateLinks(
             TextClassificationSessionId sessionId,
-            TextLinks.Request request, ITextLinksCallback callback)
+            TextLinks.Request request, ITextClassifierCallback callback)
             throws RemoteException {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(callback);
@@ -241,7 +237,7 @@
     public void onDetectLanguage(
             TextClassificationSessionId sessionId,
             TextLanguage.Request request,
-            ITextLanguageCallback callback) throws RemoteException {
+            ITextClassifierCallback callback) throws RemoteException {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(callback);
         validateInput(mContext, request.getCallingPackageName());
@@ -264,7 +260,7 @@
     public void onSuggestConversationActions(
             TextClassificationSessionId sessionId,
             ConversationActions.Request request,
-            IConversationActionsCallback callback) throws RemoteException {
+            ITextClassifierCallback callback) throws RemoteException {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(callback);
         validateInput(mContext, request.getCallingPackageName());
diff --git a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
index f26121e..f8c7447 100644
--- a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
+++ b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.provider.DeviceConfig;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.RescueParty;
 
 import java.util.ArrayList;
@@ -41,20 +42,23 @@
     /**
      * Name of the special namespace in DeviceConfig table used for communicating resets.
      */
-    private static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
+    @VisibleForTesting
+    public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
     /**
      * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link
      * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the
      * first time flags are written to the new namespace in the {@link DeviceConfig}.
      */
-    private static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
+    @VisibleForTesting
+    public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
     /**
      * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter
      * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently
      * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given
      * namespace flags are reset.
      */
-    private static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
+    @VisibleForTesting
+    public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
     private static final String DELIMITER = ":";
     /**
      * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG}
@@ -97,11 +101,25 @@
      * Reset all namespaces in DeviceConfig with consumed resetMode.
      */
     public static void resetDeviceConfig(int resetMode) {
-        List<String> allKnownNamespaces = getAllKnownDeviceConfigNamespacesList();
-        for (String namespace : allKnownNamespaces) {
+        resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList());
+    }
+
+    /**
+     * Reset all consumed namespaces in DeviceConfig with consumed resetMode.
+     */
+    public static void resetDeviceConfig(int resetMode, List<String> namespacesList) {
+        for (String namespace : namespacesList) {
             DeviceConfig.resetToDefaults(resetMode, namespace);
         }
-        addToKnownResetNamespaces(allKnownNamespaces);
+        addToKnownResetNamespaces(namespacesList);
+    }
+
+    /**
+     * Resets known reset namespaces flag counter for tests only.
+     */
+    @VisibleForTesting
+    public static void resetKnownResetNamespacesFlagCounterForTest() {
+        sKnownResetNamespacesFlagCounter = -1;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index bb1e001..e53fde9 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -474,7 +474,13 @@
         int wallpaperId;
 
         if (wallpaper.equals(mFallbackWallpaper)) {
-            extractDefaultImageWallpaperColors();
+            synchronized (mLock) {
+                if (mFallbackWallpaper.primaryColors != null) return;
+            }
+            final WallpaperColors colors = extractDefaultImageWallpaperColors();
+            synchronized (mLock) {
+                mFallbackWallpaper.primaryColors = colors;
+            }
             return;
         }
 
@@ -499,23 +505,7 @@
             }
         } else if (defaultImageWallpaper) {
             // There is no crop and source file because this is default image wallpaper.
-            try (final InputStream is =
-                         WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
-                if (is != null) {
-                    try {
-                        final BitmapFactory.Options options = new BitmapFactory.Options();
-                        final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
-                        if (bitmap != null) {
-                            colors = WallpaperColors.fromBitmap(bitmap);
-                            bitmap.recycle();
-                        }
-                    } catch (OutOfMemoryError e) {
-                        Slog.w(TAG, "Can't decode default wallpaper stream", e);
-                    }
-                }
-            } catch (IOException e) {
-                Slog.w(TAG, "Can't close default wallpaper stream", e);
-            }
+            colors = extractDefaultImageWallpaperColors();
         }
 
         if (colors == null) {
@@ -535,37 +525,41 @@
         }
     }
 
-    private void extractDefaultImageWallpaperColors() {
+    private WallpaperColors extractDefaultImageWallpaperColors() {
+        if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
+
         synchronized (mLock) {
-            if (mFallbackWallpaper.primaryColors != null) return;
+            if (mCacheDefaultImageWallpaperColors != null) return mCacheDefaultImageWallpaperColors;
         }
 
-        if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors");
         WallpaperColors colors = null;
-        final InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM);
-        if (is != null) {
-            try {
-                final BitmapFactory.Options options = new BitmapFactory.Options();
-                final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
-                if (bitmap != null) {
-                    colors = WallpaperColors.fromBitmap(bitmap);
-                    bitmap.recycle();
-                }
-            } catch (OutOfMemoryError e) {
-                Slog.w(TAG, "Can't decode default wallpaper stream", e);
-            } finally {
-                IoUtils.closeQuietly(is);
+        try (InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
+            if (is == null) {
+                Slog.w(TAG, "Can't open default wallpaper stream");
+                return null;
             }
+
+            final BitmapFactory.Options options = new BitmapFactory.Options();
+            final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
+            if (bitmap != null) {
+                colors = WallpaperColors.fromBitmap(bitmap);
+                bitmap.recycle();
+            }
+        } catch (OutOfMemoryError e) {
+            Slog.w(TAG, "Can't decode default wallpaper stream", e);
+        } catch (IOException e) {
+            Slog.w(TAG, "Can't close default wallpaper stream", e);
         }
 
         if (colors == null) {
             Slog.e(TAG, "Extract default image wallpaper colors failed");
-            return;
+        } else {
+            synchronized (mLock) {
+                mCacheDefaultImageWallpaperColors = colors;
+            }
         }
 
-        synchronized (mLock) {
-            mFallbackWallpaper.primaryColors = colors;
-        }
+        return colors;
     }
 
     /**
@@ -815,6 +809,12 @@
     private final ComponentName mImageWallpaper;
 
     /**
+     * Default image wallpaper shall never changed after system service started, caching it when we
+     * first read the image file.
+     */
+    private WallpaperColors mCacheDefaultImageWallpaperColors;
+
+    /**
      * Name of the default wallpaper component; might be different from mImageWallpaper
      */
     private final ComponentName mDefaultWallpaperComponent;
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index f882fde..a33b454d 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -126,6 +126,13 @@
     private boolean mSingleTaskInstance;
 
     /**
+     * Non-null if the last size compatibility mode activity is using non-native screen
+     * configuration. The activity is not able to put in multi-window mode, so it exists only one
+     * per display.
+     */
+    private ActivityRecord mLastCompatModeActivity;
+
+    /**
      * A focusable stack that is purposely to be positioned at the top. Although the stack may not
      * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
      * target stack properly when there are other focusable always-on-top stacks.
@@ -1032,6 +1039,28 @@
         mSplitScreenPrimaryStack = null;
     }
 
+    /** Checks whether the given activity is in size compatibility mode and notifies the change. */
+    void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
+        if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+            // The callback is only interested in the foreground changes of fullscreen activity.
+            return;
+        }
+        if (!r.inSizeCompatMode()) {
+            if (mLastCompatModeActivity != null) {
+                mService.getTaskChangeNotificationController()
+                        .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
+            }
+            mLastCompatModeActivity = null;
+            return;
+        }
+        if (mLastCompatModeActivity == r) {
+            return;
+        }
+        mLastCompatModeActivity = r;
+        mService.getTaskChangeNotificationController()
+                .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
+    }
+
     ActivityStack getSplitScreenPrimaryStack() {
         return mSplitScreenPrimaryStack;
     }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f70adef..4706930 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -101,6 +101,7 @@
 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
@@ -160,6 +161,7 @@
 import android.app.servertransaction.PauseActivityItem;
 import android.app.servertransaction.PipModeChangeItem;
 import android.app.servertransaction.ResumeActivityItem;
+import android.app.servertransaction.StopActivityItem;
 import android.app.servertransaction.TopResumedActivityChangeItem;
 import android.app.servertransaction.WindowVisibilityItem;
 import android.app.usage.UsageEvents.Event;
@@ -564,11 +566,8 @@
             pw.print("requestedVrComponent=");
             pw.println(requestedVrComponent);
         }
-        final boolean waitingVisible =
-                mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this);
-        if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
-            pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
-                    pw.print(" nowVisible="); pw.print(nowVisible);
+        if (lastVisibleTime != 0 || nowVisible) {
+            pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
                     pw.print(" lastVisibleTime=");
                     if (lastVisibleTime == 0) pw.print("0");
                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
@@ -2131,6 +2130,11 @@
             r.icicle = null;
             r.haveState = false;
         }
+
+        final ActivityDisplay display = r.getDisplay();
+        if (display != null) {
+            display.handleActivitySizeCompatModeIfNeeded(r);
+        }
     }
 
     /**
@@ -2192,7 +2196,8 @@
     final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
             CharSequence description) {
         final ActivityStack stack = getActivityStack();
-        if (mState != STOPPING) {
+        final boolean isStopping = mState == STOPPING;
+        if (!isStopping && mState != RESTARTING_PROCESS) {
             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
             return;
@@ -2215,7 +2220,9 @@
             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
             stopped = true;
-            setState(STOPPED, "activityStoppedLocked");
+            if (isStopping) {
+                setState(STOPPED, "activityStoppedLocked");
+            }
 
             if (mAppWindowToken != null) {
                 mAppWindowToken.notifyAppStopped();
@@ -2358,27 +2365,6 @@
             if (!nowVisible) {
                 nowVisible = true;
                 lastVisibleTime = SystemClock.uptimeMillis();
-                if (idle || mStackSupervisor.isStoppingNoHistoryActivity()) {
-                    // If this activity was already idle or there is an activity that must be
-                    // stopped immediately after visible, then we now need to make sure we perform
-                    // the full stop of any activities that are waiting to do so. This is because
-                    // we won't do that while they are still waiting for this one to become visible.
-                    final int size = mStackSupervisor.mActivitiesWaitingForVisibleActivity.size();
-                    if (size > 0) {
-                        for (int i = 0; i < size; i++) {
-                            final ActivityRecord r =
-                                    mStackSupervisor.mActivitiesWaitingForVisibleActivity.get(i);
-                            if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
-                        }
-                        mStackSupervisor.mActivitiesWaitingForVisibleActivity.clear();
-                        mStackSupervisor.scheduleIdleLocked();
-                    }
-                } else {
-                    // Instead of doing the full stop routine here, let's just hide any activities
-                    // we now can, and let them stop when the normal idle happens.
-                    mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
-                            false /* remove */, true /* processPausingActivities */);
-                }
                 mAtmService.scheduleAppGcsLocked();
             }
         }
@@ -2392,6 +2378,24 @@
         }
     }
 
+    void onAnimationFinished() {
+        if (mRootActivityContainer.allResumedActivitiesIdle()
+                || mStackSupervisor.isStoppingNoHistoryActivity()) {
+            // If all activities are already idle or there is an activity that must be
+            // stopped immediately after visible, then we now need to make sure we perform
+            // the full stop of this activity. This is because we won't do that while they are still
+            // waiting for the animation to finish.
+            if (mStackSupervisor.mStoppingActivities.contains(this)) {
+                mStackSupervisor.scheduleIdleLocked();
+            }
+        } else {
+            // Instead of doing the full stop routine here, let's just hide any activities
+            // we now can, and let them stop when the normal idle happens.
+            mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
+                    false /* remove */, true /* processPausingActivities */);
+        }
+    }
+
     /**
      * Called when the key dispatching to a window associated with the app window container
      * timed-out.
@@ -2424,10 +2428,9 @@
     }
 
     private ActivityRecord getWaitingHistoryRecordLocked() {
-        // First find the real culprit...  if this activity is waiting for
-        // another activity to start or has stopped, then the key dispatching
+        // First find the real culprit...  if this activity has stopped, then the key dispatching
         // timeout should not be caused by this.
-        if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
+        if (stopped) {
             final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
             // Try to use the one which is closest to top.
             ActivityRecord r = stack.getResumedActivity();
@@ -2700,13 +2703,39 @@
     }
 
     /**
+     * @return {@code true} if this activity is in size compatibility mode that uses the different
+     *         density or bounds from its parent.
+     */
+    boolean inSizeCompatMode() {
+        if (!shouldUseSizeCompatMode()) {
+            return false;
+        }
+        final Configuration parentConfig = getParent().getConfiguration();
+        final Configuration resolvedConfig = getResolvedOverrideConfiguration();
+        // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
+        // fields should be changed with density and bounds, so here only compares the most
+        // significant field.
+        if (parentConfig.densityDpi != resolvedConfig.densityDpi) {
+            return true;
+        }
+        final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
+        final Rect parentBounds = parentAppBounds != null
+                ? parentAppBounds : parentConfig.windowConfiguration.getBounds();
+        final Rect overrideBounds = resolvedConfig.windowConfiguration.getBounds();
+        // If the width or height is the same as parent, it is already the best fit of the override
+        // bounds, therefore this condition is considered as not size compatibility mode.
+        return parentBounds.width() != overrideBounds.width()
+                && parentBounds.height() != overrideBounds.height();
+    }
+
+    /**
      * Indicates the activity will keep the bounds and screen configuration when it was first
      * launched, no matter how its parent changes.
      *
      * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
      *         aspect ratio.
      */
-    private boolean inSizeCompatMode() {
+    private boolean shouldUseSizeCompatMode() {
         return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
                 // The configuration of non-standard type should be enforced by system.
                 && isActivityTypeStandard()
@@ -2715,8 +2744,8 @@
 
     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
     private void updateOverrideConfiguration() {
-        final boolean inSizeCompatMode = inSizeCompatMode();
-        if (inSizeCompatMode) {
+        final boolean shouldUseSizeCompatMode = shouldUseSizeCompatMode();
+        if (shouldUseSizeCompatMode) {
             if (!matchParentBounds()) {
                 // The override configuration is set only once in size compatible mode.
                 return;
@@ -2731,7 +2760,7 @@
 
         computeBounds(mTmpBounds);
 
-        if (inSizeCompatMode && mTmpBounds.isEmpty()) {
+        if (shouldUseSizeCompatMode && mTmpBounds.isEmpty()) {
             mTmpBounds.set(task.getWindowConfiguration().getBounds());
         }
         if (mTmpBounds.equals(getRequestedOverrideBounds())) {
@@ -2743,7 +2772,7 @@
         overrideConfig.unset();
         if (!mTmpBounds.isEmpty()) {
             overrideConfig.windowConfiguration.setBounds(mTmpBounds);
-            if (inSizeCompatMode) {
+            if (shouldUseSizeCompatMode) {
                 // Ensure the screen related fields are set. It is used to prevent activity relaunch
                 // when moving between displays. For screenWidthDp and screenWidthDp, because they
                 // are relative to bounds and density, they will be calculated in
@@ -2778,7 +2807,7 @@
         }
 
         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
-        if (!inSizeCompatMode()) {
+        if (!shouldUseSizeCompatMode()) {
             computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
                     ORIENTATION_UNDEFINED, true /* insideParentBounds */);
             return;
@@ -2858,6 +2887,11 @@
                     getResolvedOverrideConfiguration().seq;
             mAppWindowToken.onMergedOverrideConfigurationChanged();
         }
+
+        final ActivityDisplay display = getDisplay();
+        if (display != null) {
+            display.handleActivitySizeCompatModeIfNeeded(this);
+        }
     }
 
     /** Returns true if the configuration is compatible with this activity. */
@@ -2992,7 +3026,7 @@
      *                        state. This is useful for the case where we know the activity will be
      *                        visible soon and we want to ensure its configuration before we make it
      *                        visible.
-     * @return True if the activity was relaunched and false if it wasn't relaunched because we
+     * @return False if the activity was relaunched and true if it wasn't relaunched because we
      *         can't or the app handles the specific configuration that is changing.
      */
     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
@@ -3314,6 +3348,54 @@
         preserveWindowOnDeferredRelaunch = false;
     }
 
+    /**
+     * Request the process of the activity to restart with its saved state (from
+     * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
+     * the override configuration. Note if the activity is in background, the process will be killed
+     * directly with keeping its record.
+     */
+    void restartProcessIfVisible() {
+        Slog.i(TAG, "Request to restart process of " + this);
+
+        // Reset the existing override configuration to the latest configuration.
+        getRequestedOverrideConfiguration().setToDefaults();
+        getResolvedOverrideConfiguration().setToDefaults();
+        if (visible) {
+            // Configuration will be ensured when becoming visible, so if it is already visible,
+            // then the manual update is needed.
+            updateOverrideConfiguration();
+        }
+
+        if (!attachedToProcess()) {
+            return;
+        }
+
+        // The restarting state avoids removing this record when process is died.
+        setState(RESTARTING_PROCESS, "restartActivityProcess");
+
+        if (!visible || haveState) {
+            // Kill its process immediately because the activity should be in background.
+            // The activity state will be update to {@link #DESTROYED} in
+            // {@link ActivityStack#cleanUpActivityLocked} when handling process died.
+            mAtmService.mH.post(() -> mAtmService.mAmInternal.killProcess(
+                    app.mName, app.mUid, "restartActivityProcess"));
+            return;
+        }
+
+        if (mAppWindowToken != null) {
+            mAppWindowToken.startFreezingScreen();
+        }
+        // The process will be killed until the activity reports stopped with saved state (see
+        // {@link ActivityTaskManagerService.activityStopped}).
+        try {
+            mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+                    StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Exception thrown during restart " + this, e);
+        }
+        mStackSupervisor.scheduleRestartTimeout(this);
+    }
+
     private boolean isProcessRunning() {
         WindowProcessController proc = app;
         if (proc == null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ea2aff2..ad98970 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -297,7 +297,8 @@
         STOPPED,
         FINISHING,
         DESTROYING,
-        DESTROYED
+        DESTROYED,
+        RESTARTING_PROCESS
     }
 
     @VisibleForTesting
@@ -701,6 +702,14 @@
      */
     void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
             boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) {
+        mWindowManager.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
+                preferredWindowingMode, animate, showRecents, enteringSplitScreenMode,
+                deferEnsuringVisibility, creating));
+    }
+
+    private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate,
+            boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility,
+            boolean creating) {
         final int currentMode = getWindowingMode();
         final int currentOverrideMode = getRequestedOverrideWindowingMode();
         final ActivityDisplay display = getDisplay();
@@ -744,7 +753,7 @@
                 // warning toast about it.
                 mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
                 final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack();
-                primarySplitStack.setWindowingMode(WINDOWING_MODE_UNDEFINED,
+                primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED,
                         false /* animate */, false /* showRecents */,
                         false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
                         primarySplitStack == this ? creating : false);
@@ -1799,10 +1808,6 @@
             } else if (prev.hasProcess()) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                         + " wasStopping=" + wasStopping + " visible=" + prev.visible);
-                if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
-                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
-                            "Complete pause, no longer waiting: " + prev);
-                }
                 if (prev.deferRelaunchUntilPaused) {
                     // Complete the deferred relaunch that was waiting for pause to complete.
                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
@@ -1882,16 +1887,6 @@
     private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
             mStackSupervisor.mStoppingActivities.add(r);
-
-            // Some activity is waiting for another activity to become visible before it's being
-            // stopped, which means that we also want to wait with stopping this one to avoid
-            // flickers.
-            if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.isEmpty()
-                    && !mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
-                if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "adding to waiting visible activity=" + r
-                        + " existing=" + mStackSupervisor.mActivitiesWaitingForVisibleActivity);
-                mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
-            }
         }
 
         // If we already have a few activities waiting to stop, then give up
@@ -2707,7 +2702,6 @@
         mStackSupervisor.mStoppingActivities.remove(next);
         mStackSupervisor.mGoingToSleepActivities.remove(next);
         next.sleeping = false;
-        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
 
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
 
@@ -2716,11 +2710,6 @@
             if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                     "resumeTopActivityLocked: Skip resume: some activity pausing.");
 
-            // Adding previous activity to the waiting visible list, or it would be stopped
-            // before top activity being visible.
-            if (prev != null && !next.nowVisible) {
-                mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
-            }
             return false;
         }
 
@@ -2796,35 +2785,27 @@
             mLastNoHistoryActivity = null;
         }
 
-        if (prev != null && prev != next) {
-            if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
-                    && !next.nowVisible) {
-                mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
+        if (prev != null && prev != next && next.nowVisible) {
+
+            // The next activity is already visible, so hide the previous
+            // activity's windows right now so we can show the new one ASAP.
+            // We only do this if the previous is finishing, which should mean
+            // it is on top of the one being resumed so hiding it quickly
+            // is good.  Otherwise, we want to do the normal route of allowing
+            // the resumed activity to be shown so we can decide if the
+            // previous should actually be hidden depending on whether the
+            // new one is found to be full-screen or not.
+            if (prev.finishing) {
+                prev.setVisibility(false);
                 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
-                        "Resuming top, waiting visible to hide: " + prev);
+                        "Not waiting for visible to hide: " + prev
+                        + ", nowVisible=" + next.nowVisible);
             } else {
-                // The next activity is already visible, so hide the previous
-                // activity's windows right now so we can show the new one ASAP.
-                // We only do this if the previous is finishing, which should mean
-                // it is on top of the one being resumed so hiding it quickly
-                // is good.  Otherwise, we want to do the normal route of allowing
-                // the resumed activity to be shown so we can decide if the
-                // previous should actually be hidden depending on whether the
-                // new one is found to be full-screen or not.
-                if (prev.finishing) {
-                    prev.setVisibility(false);
-                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
-                            "Not waiting for visible to hide: " + prev + ", waitingVisible="
-                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
-                            + ", nowVisible=" + next.nowVisible);
-                } else {
-                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
-                            "Previous already visible but still waiting to hide: " + prev
-                            + ", waitingVisible="
-                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
-                            + ", nowVisible=" + next.nowVisible);
-                }
+                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
+                        "Previous already visible but still waiting to hide: " + prev
+                        + ", nowVisible=" + next.nowVisible);
             }
+
         }
 
         // Launching this app's activity, make sure the app is no longer
@@ -4081,9 +4062,6 @@
         dc.prepareAppTransition(transit, false);
         r.setVisibility(false);
         dc.executeAppTransition();
-        if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
-            mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
-        }
     }
 
     static final int FINISH_IMMEDIATELY = 0;
@@ -4119,7 +4097,6 @@
         // make sure the record is cleaned out of other places.
         mStackSupervisor.mStoppingActivities.remove(r);
         mStackSupervisor.mGoingToSleepActivities.remove(r);
-        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
         final ActivityState prevState = r.getState();
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
 
@@ -4725,8 +4702,6 @@
                 "mStoppingActivities");
         removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
                 "mGoingToSleepActivities");
-        removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app,
-                "mActivitiesWaitingForVisibleActivity");
         removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
                 "mFinishingActivities");
 
@@ -4767,7 +4742,8 @@
                         // it has failed more than twice. Skip activities that's already finishing
                         // cleanly by itself.
                         remove = false;
-                    } else if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
+                    } else if ((!r.haveState && !r.stateNotNeeded
+                            && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) {
                         // Don't currently have state for the activity, or
                         // it is finishing -- always remove it.
                         remove = true;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 758a765..1ae85b8 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -179,6 +179,7 @@
     static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
     static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
     static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
+    static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 13;
     static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
     static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;
     static final int REPORT_HOME_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 16;
@@ -267,12 +268,6 @@
      */
     private final SparseIntArray mCurTaskIdForUser = new SparseIntArray(20);
 
-    /** List of activities that are waiting for a new activity to become visible before completing
-     * whatever operation they are supposed to do. */
-    // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from
-    // mStoppingActivities when something else comes up.
-    final ArrayList<ActivityRecord> mActivitiesWaitingForVisibleActivity = new ArrayList<>();
-
     /** List of processes waiting to find out when a specific activity becomes visible. */
     private final ArrayList<WaitInfo> mWaitingForActivityVisible = new ArrayList<>();
 
@@ -550,7 +545,6 @@
         // This could happen, for example, if we are trimming activities
         // down to the max limit while they are still waiting to finish.
         mFinishingActivities.remove(r);
-        mActivitiesWaitingForVisibleActivity.remove(r);
 
         for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
             if (mWaitingForActivityVisible.get(i).matches(r.mActivityComponent)) {
@@ -2142,28 +2136,27 @@
         final boolean nowVisible = mRootActivityContainer.allResumedActivitiesVisible();
         for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
             ActivityRecord s = mStoppingActivities.get(activityNdx);
-            boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s);
+
+            final boolean animating = s.mAppWindowToken.isSelfAnimating();
+
             if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
-                    + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
-            if (waitingVisible && nowVisible) {
-                mActivitiesWaitingForVisibleActivity.remove(s);
-                waitingVisible = false;
-                if (s.finishing) {
-                    // If this activity is finishing, it is sitting on top of
-                    // everyone else but we now know it is no longer needed...
-                    // so get rid of it.  Otherwise, we need to go through the
-                    // normal flow and hide it once we determine that it is
-                    // hidden by the activities in front of it.
-                    if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
-                    s.setVisibility(false);
-                }
+                    + " animating=" + animating + " finishing=" + s.finishing);
+            if (nowVisible && s.finishing) {
+
+                // If this activity is finishing, it is sitting on top of
+                // everyone else but we now know it is no longer needed...
+                // so get rid of it.  Otherwise, we need to go through the
+                // normal flow and hide it once we determine that it is
+                // hidden by the activities in front of it.
+                if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
+                s.setVisibility(false);
             }
             if (remove) {
                 final ActivityStack stack = s.getActivityStack();
                 final boolean shouldSleepOrShutDown = stack != null
                         ? stack.shouldSleepOrShutDownActivities()
                         : mService.isSleepingOrShuttingDownLocked();
-                if (!waitingVisible || shouldSleepOrShutDown) {
+                if (!animating || shouldSleepOrShutDown) {
                     if (!processPausingActivities && s.isState(PAUSING)) {
                         // Defer processing pausing activities in this iteration and reschedule
                         // a delayed idle to reprocess it again
@@ -2178,9 +2171,6 @@
                     }
                     stops.add(s);
 
-                    // Make sure to remove it in all cases in case we entered this block with
-                    // shouldSleepOrShutDown
-                    mActivitiesWaitingForVisibleActivity.remove(s);
                     mStoppingActivities.remove(activityNdx);
                 }
             }
@@ -2400,6 +2390,16 @@
         mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
     }
 
+    void removeRestartTimeouts(ActivityRecord r) {
+        mHandler.removeMessages(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r);
+    }
+
+    final void scheduleRestartTimeout(ActivityRecord r) {
+        removeRestartTimeouts(r);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG, r),
+                WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION);
+    }
+
     void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
             int preferredDisplayId, ActivityStack actualStack) {
         handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
@@ -2430,17 +2430,17 @@
             final boolean singleTaskInstance = preferredDisplay != null
                     && preferredDisplay.isSingleTaskInstance();
 
-            if (singleTaskInstance) {
+            if (preferredDisplayId != actualDisplayId) {
                 // Suppress the warning toast if the preferredDisplay was set to singleTask.
                 // The singleTaskInstance displays will only contain one task and any attempt to
                 // launch new task will re-route to the default display.
-                mService.getTaskChangeNotificationController()
-                        .notifyActivityLaunchOnSecondaryDisplayRerouted(task.getTaskInfo(),
-                                preferredDisplayId);
-                return;
-            }
+                if (singleTaskInstance) {
+                    mService.getTaskChangeNotificationController()
+                            .notifyActivityLaunchOnSecondaryDisplayRerouted(task.getTaskInfo(),
+                                    preferredDisplayId);
+                    return;
+                }
 
-            if (preferredDisplayId != actualDisplayId) {
                 Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
                 // Display a warning toast that we failed to put a task on a secondary display.
                 mService.getTaskChangeNotificationController()
@@ -2666,6 +2666,22 @@
                         }
                     }
                 } break;
+                case RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG: {
+                    final ActivityRecord r = (ActivityRecord) msg.obj;
+                    String processName = null;
+                    int uid = 0;
+                    synchronized (mService.mGlobalLock) {
+                        if (r.attachedToProcess()
+                                && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) {
+                            processName = r.app.mName;
+                            uid = r.app.mUid;
+                        }
+                    }
+                    if (processName != null) {
+                        mService.mAmInternal.killProcess(processName, uid,
+                                "restartActivityProcessTimeout");
+                    }
+                } break;
                 case REPORT_HOME_CHANGED_MSG: {
                     synchronized (mService.mGlobalLock) {
                         mHandler.removeMessages(REPORT_HOME_CHANGED_MSG);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 9f04166..23bed7b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1009,6 +1009,12 @@
         if (mService.isDeviceOwner(callingPackage)) {
             return false;
         }
+        // don't abort if the callingPackage is temporarily whitelisted
+        if (mService.isPackageNameWhitelistedForBgActivityStarts(callingPackage)) {
+            Slog.w(TAG, "Background activity start for " + callingPackage
+                    + " temporarily whitelisted. This will not be supported in future Q builds.");
+            return false;
+        }
         // anything that has fallen through would currently be aborted
         Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                 + "; callingUid: " + callingUid
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d747198..f100efc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -776,6 +776,12 @@
         return mGlobalLock;
     }
 
+    /** For test purpose only. */
+    @VisibleForTesting
+    public ActivityTaskManagerInternal getAtmInternal() {
+        return mInternal;
+    }
+
     public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController,
             Looper looper) {
         mH = new H(looper);
@@ -1666,13 +1672,32 @@
 
         final long origId = Binder.clearCallingIdentity();
 
+        String restartingName = null;
+        int restartingUid = 0;
+        final ActivityRecord r;
         synchronized (mGlobalLock) {
-            final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
+                if (r.attachedToProcess()
+                        && r.isState(ActivityStack.ActivityState.RESTARTING_PROCESS)) {
+                    // The activity was requested to restart from
+                    // {@link #restartActivityProcessIfVisible}.
+                    restartingName = r.app.mName;
+                    restartingUid = r.app.mUid;
+                }
                 r.activityStoppedLocked(icicle, persistentState, description);
             }
         }
 
+        if (restartingName != null) {
+            // In order to let the foreground activity can be restarted with its saved state from
+            // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed
+            // until the activity reports stopped with the state. And the activity record will be
+            // kept because the record state is restarting, then the activity will be restarted
+            // immediately if it is still the top one.
+            mStackSupervisor.removeRestartTimeouts(r);
+            mAmInternal.killProcess(restartingName, restartingUid, "restartActivityProcess");
+        }
         mAmInternal.trimApplications();
 
         Binder.restoreCallingIdentity(origId);
@@ -2014,6 +2039,23 @@
     }
 
     @Override
+    public void restartActivityProcessIfVisible(IBinder activityToken) {
+        mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "restartActivityProcess()");
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
+                if (r == null) {
+                    return;
+                }
+                r.restartProcessIfVisible();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
+    @Override
     public boolean removeTask(int taskId) {
         enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
         synchronized (mGlobalLock) {
@@ -5210,6 +5252,10 @@
         return mAmInternal.isBackgroundActivityStartsEnabled();
     }
 
+    boolean isPackageNameWhitelistedForBgActivityStarts(String packageName) {
+        return mAmInternal.isPackageNameWhitelistedForBgActivityStarts(packageName);
+    }
+
     void enableScreenAfterBoot(boolean booted) {
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
                 SystemClock.uptimeMillis());
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 19ff438..bb5a221 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -86,6 +86,7 @@
 import android.content.res.Configuration;
 import android.content.res.ResourceId;
 import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -123,6 +124,7 @@
 import android.view.animation.TranslateAnimation;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils.Dump;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AttributeCache;
@@ -558,19 +560,19 @@
         }
         resId = updateToTranslucentAnimIfNeeded(resId, transit);
         if (ResourceId.isValid(resId)) {
-            return AnimationUtils.loadAnimation(context, resId);
+            return loadAnimationSafely(context, resId);
         }
         return null;
     }
 
-    Animation loadAnimationRes(LayoutParams lp, int resId) {
+    private Animation loadAnimationRes(LayoutParams lp, int resId) {
         Context context = mContext;
         if (ResourceId.isValid(resId)) {
             AttributeCache.Entry ent = getCachedAnimations(lp);
             if (ent != null) {
                 context = ent.context;
             }
-            return AnimationUtils.loadAnimation(context, resId);
+            return loadAnimationSafely(context, resId);
         }
         return null;
     }
@@ -579,12 +581,22 @@
         if (ResourceId.isValid(resId)) {
             AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
             if (ent != null) {
-                return AnimationUtils.loadAnimation(ent.context, resId);
+                return loadAnimationSafely(ent.context, resId);
             }
         }
         return null;
     }
 
+    @VisibleForTesting
+    Animation loadAnimationSafely(Context context, int resId) {
+        try {
+            return AnimationUtils.loadAnimation(context, resId);
+        } catch (NotFoundException e) {
+            Slog.w(TAG, "Unable to load animation resource", e);
+            return null;
+        }
+    }
+
     private int updateToTranslucentAnimIfNeeded(int anim, int transit) {
         if (transit == TRANSIT_TRANSLUCENT_ACTIVITY_OPEN && anim == R.anim.activity_open_enter) {
             return R.anim.activity_translucent_open_enter;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 78199d44..220370c 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -2784,6 +2784,8 @@
 
         getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
         scheduleAnimation();
+
+        mActivityRecord.onAnimationFinished();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index f8f693c..3110fb9 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -236,6 +236,7 @@
                     .setFlags(HIDDEN).setColorLayer().build();
             mSurface.setLayer(-1);
             mSurface.setColor(new float[]{0, 0, 0});
+            mSurface.setColorSpaceAgnostic(true);
         }
 
         void attachInput(WindowState win) {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index e3beb19..f964b57 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -362,6 +362,8 @@
         if (displayId == DEFAULT_DISPLAY) {
             homeIntent = mService.getHomeIntent();
             aInfo = resolveHomeActivity(userId, homeIntent);
+        } else if (!mService.mSupportsMultiDisplay) {
+            return false;
         } else {
             Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId);
             aInfo = info.first;
@@ -544,6 +546,11 @@
             return true;
         }
 
+        if (displayId != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) {
+            // Can't launch home on secondary display if device not support multi-display.
+            return false;
+        }
+
         final boolean deviceProvisioned = Settings.Global.getInt(
                 mService.mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
@@ -2016,8 +2023,7 @@
                 final ActivityStack stack = display.getChildAt(stackNdx);
                 final ActivityRecord r = stack.getResumedActivity();
                 if (r != null) {
-                    if (!r.nowVisible
-                            || mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
+                    if (!r.nowVisible) {
                         return false;
                     }
                     foundResumed = true;
@@ -2345,10 +2351,6 @@
         printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, "  ",
                 "Stop", false, !dumpAll,
                 false, dumpPackage, true, "  Activities waiting to stop:", null);
-        printed |= dumpHistoryList(fd, pw,
-                mStackSupervisor.mActivitiesWaitingForVisibleActivity, "  ", "Wait",
-                false, !dumpAll, false, dumpPackage, true,
-                "  Activities waiting for another to become visible:", null);
         printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities,
                 "  ", "Sleep", false, !dumpAll,
                 false, dumpPackage, true, "  Activities waiting to sleep:", null);
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 42d2583..3d57219 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -24,6 +24,7 @@
 import android.content.ComponentName;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteCallbackList;
@@ -51,6 +52,7 @@
     private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
     private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
+    private static final int NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG = 20;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -143,6 +145,10 @@
         l.onTaskSnapshotChanged(m.arg1, (TaskSnapshot) m.obj);
     };
 
+    private final TaskStackConsumer mOnSizeCompatModeActivityChanged = (l, m) -> {
+        l.onSizeCompatModeActivityChanged(m.arg1, (IBinder) m.obj);
+    };
+
     @FunctionalInterface
     public interface TaskStackConsumer {
         void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -216,6 +222,9 @@
                 case NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyTaskSnapshotChanged, msg);
                     break;
+                case NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG:
+                    forAllRemoteListeners(mOnSizeCompatModeActivityChanged, msg);
+                    break;
             }
         }
     }
@@ -438,4 +447,15 @@
         forAllLocalListeners(mNotifyTaskSnapshotChanged, msg);
         msg.sendToTarget();
     }
+
+    /**
+     * Notify listeners that whether a size compatibility mode activity is using the override
+     * bounds which is not fit its parent.
+     */
+    void notifySizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
+        final Message msg = mHandler.obtainMessage(NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG,
+                displayId, 0 /* unused */, activityToken);
+        forAllLocalListeners(mOnSizeCompatModeActivityChanged, msg);
+        msg.sendToTarget();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 1392762..4fd8489 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -202,13 +202,6 @@
     // Do not move the stack as a part of reparenting
     static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
 
-    // The height/width divide used when fitting a task within a bounds with method
-    // {@link #fitWithinBounds}.
-    // We always want the task to to be visible in the bounds without affecting its size when
-    // fitting. To make sure this is the case, we don't adjust the task left or top side pass
-    // the input bounds right or bottom side minus the width or height divided by this value.
-    private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
-
     /**
      * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
      */
@@ -1932,35 +1925,33 @@
      *
      * @param bounds Bounds to be adjusted.
      * @param stackBounds Bounds within which the other bounds should remain.
+     * @param overlapPxX The amount of px required to be visible in the X dimension.
+     * @param overlapPxY The amount of px required to be visible in the Y dimension.
      */
-    private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
+    private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
+            int overlapPxY) {
         if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
             return;
         }
 
-        if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
-            final int maxRight = stackBounds.right
-                    - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
-            int horizontalDiff = stackBounds.left - bounds.left;
-            if ((horizontalDiff < 0 && bounds.left >= maxRight)
-                    || (bounds.left + horizontalDiff >= maxRight)) {
-                horizontalDiff = maxRight - bounds.left;
-            }
-            bounds.left += horizontalDiff;
-            bounds.right += horizontalDiff;
+        // For each side of the parent (eg. left), check if the opposing side of the window (eg.
+        // right) is at least overlap pixels away. If less, offset the window by that difference.
+        int horizontalDiff = 0;
+        // If window is smaller than overlap, use it's smallest dimension instead
+        int overlapLR = Math.min(overlapPxX, bounds.width());
+        if (bounds.right < (stackBounds.left + overlapLR)) {
+            horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
+        } else if (bounds.left > (stackBounds.right - overlapLR)) {
+            horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
         }
-
-        if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
-            final int maxBottom = stackBounds.bottom
-                    - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
-            int verticalDiff = stackBounds.top - bounds.top;
-            if ((verticalDiff < 0 && bounds.top >= maxBottom)
-                    || (bounds.top + verticalDiff >= maxBottom)) {
-                verticalDiff = maxBottom - bounds.top;
-            }
-            bounds.top += verticalDiff;
-            bounds.bottom += verticalDiff;
+        int verticalDiff = 0;
+        int overlapTB = Math.min(overlapPxY, bounds.width());
+        if (bounds.bottom < (stackBounds.top + overlapTB)) {
+            verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
+        } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
+            verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
         }
+        bounds.offset(horizontalDiff, verticalDiff);
     }
 
     /**
@@ -2230,7 +2221,11 @@
         adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
         if (windowingMode == WINDOWING_MODE_FREEFORM) {
             // by policy, make sure the window remains within parent somewhere
-            fitWithinBounds(outOverrideBounds, newParentConfig.windowConfiguration.getBounds());
+            final float density =
+                    ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
+            fitWithinBounds(outOverrideBounds, newParentConfig.windowConfiguration.getBounds(),
+                    (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
+                    (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
         }
         computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d58e204..e3a8be5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -232,6 +232,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.policy.IShortcutService;
@@ -414,6 +415,14 @@
         @Override
         public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args,
                 boolean asProto) {
+            // Bugreport dumps the trace 2x, 1x as proto and 1x as text. Save file to disk only 1x.
+            if (asProto && mWindowTracing.isEnabled()) {
+                mWindowTracing.stopTrace(null, false /* writeToFile */);
+                BackgroundThread.getHandler().post(() -> {
+                    mWindowTracing.writeTraceToFile();
+                    mWindowTracing.startTrace(null);
+                });
+            }
             doDump(fd, pw, new String[] {"-a"}, asProto);
         }
 
@@ -1179,8 +1188,7 @@
                         + displayId + ".  Aborting.");
                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
             }
-            if (!displayContent.hasAccess(session.mUid)
-                    && !mDisplayManagerInternal.isUidPresentOnDisplay(session.mUid, displayId)) {
+            if (!displayContent.hasAccess(session.mUid)) {
                 Slog.w(TAG_WM, "Attempted to add window to a display for which the application "
                         + "does not have access: " + displayId + ".  Aborting.");
                 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
@@ -1986,6 +1994,10 @@
                     updateNonSystemOverlayWindowsVisibilityIfNeeded(
                             win, win.mWinAnimator.getShown());
                 }
+                if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {
+                    winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
+                            & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
+                }
             }
 
             if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
@@ -6183,9 +6195,6 @@
                 return;
             } else if ("trace".equals(cmd)) {
                 dumpTraceStatus(pw);
-                synchronized (mGlobalLock) {
-                    mWindowTracing.writeTraceToFile();
-                }
                 return;
             } else {
                 // Dumping a single name?
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d5a6f00..20cca66 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -942,29 +942,9 @@
         // Make sure the content and visible frames are inside of the
         // final window frame.
         if (windowsAreFloating && !mWindowFrames.mFrame.isEmpty()) {
-            // For pinned workspace the frame isn't limited in any particular
-            // way since SystemUI controls the bounds. For freeform however
-            // we want to keep things inside the content frame.
-            final Rect limitFrame = task.inPinnedWindowingMode() ? mWindowFrames.mFrame
-                    : mWindowFrames.mContentFrame;
-            // Keep the frame out of the blocked system area, limit it in size to the content area
-            // and make sure that there is always a minimum visible so that the user can drag it
-            // into a usable area..
-            final int height = Math.min(mWindowFrames.mFrame.height(), limitFrame.height());
-            final int width = Math.min(limitFrame.width(), mWindowFrames.mFrame.width());
-            final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
-            final int minVisibleHeight = Math.min(height, WindowManagerService.dipToPixel(
-                    MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics));
-            final int minVisibleWidth = Math.min(width, WindowManagerService.dipToPixel(
-                    MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics));
-            final int top = Math.max(limitFrame.top,
-                    Math.min( mWindowFrames.mFrame.top, limitFrame.bottom - minVisibleHeight));
-            final int left = Math.max(limitFrame.left + minVisibleWidth - width,
-                    Math.min( mWindowFrames.mFrame.left, limitFrame.right - minVisibleWidth));
-            mWindowFrames.mFrame.set(left, top, left + width, top + height);
             final int visBottom = mWindowFrames.mVisibleFrame.bottom;
             final int contentBottom = mWindowFrames.mContentFrame.bottom;
-            mWindowFrames.mContentFrame.set( mWindowFrames.mFrame);
+            mWindowFrames.mContentFrame.set(mWindowFrames.mFrame);
             mWindowFrames.mVisibleFrame.set(mWindowFrames.mContentFrame);
             mWindowFrames.mStableFrame.set(mWindowFrames.mContentFrame);
             if (isImeTarget && inFreeformWindowingMode()) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 969ced4..92bb082 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -487,6 +487,8 @@
             mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
                     attrs.getTitle().toString(), width, height, format, flags, this,
                     windowType, ownerUid);
+            mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
+                    & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
 
             setOffsetPositionForStackResize(false);
             mSurfaceFormat = format;
@@ -1258,6 +1260,13 @@
         mSurfaceController.setSecure(isSecure);
     }
 
+    void setColorSpaceAgnosticLocked(boolean agnostic) {
+        if (mSurfaceController == null) {
+            return;
+        }
+        mSurfaceController.setColorSpaceAgnostic(agnostic);
+    }
+
     /**
      * Have the surface flinger show a surface, robustly dealing with
      * error conditions.  In particular, if there is not enough memory
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index e796b99..acb9823 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -399,6 +399,28 @@
         }
     }
 
+    void setColorSpaceAgnostic(boolean agnostic) {
+        if (SHOW_TRANSACTIONS) {
+            logSurface("isColorSpaceAgnostic=" + agnostic, null);
+        }
+
+        if (mSurfaceControl == null) {
+            return;
+        }
+        if (SHOW_LIGHT_TRANSACTIONS) {
+            Slog.i(TAG, ">>> OPEN TRANSACTION setColorSpaceAgnosticLocked");
+        }
+        mService.openSurfaceTransaction();
+        try {
+            mSurfaceControl.setColorSpaceAgnostic(agnostic);
+        } finally {
+            mService.closeSurfaceTransaction("setColorSpaceAgnostic");
+            if (SHOW_LIGHT_TRANSACTIONS) {
+                Slog.i(TAG, "<<< CLOSE TRANSACTION setColorSpaceAgnosticLocked");
+            }
+        }
+    }
+
     void getContainerRect(Rect rect) {
         mAnimator.getContainerRect(rect);
     }
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 48b9340..4cf2344 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -100,7 +100,20 @@
         }
     }
 
+    /**
+     * Stops the trace and write the current buffer to disk
+     * @param pw Print writer
+     */
     void stopTrace(@Nullable PrintWriter pw) {
+        stopTrace(pw, true /* writeToFile */);
+    }
+
+    /**
+     * Stops the trace
+     * @param pw Print writer
+     * @param writeToFile If the current buffer should be written to disk or not
+     */
+    void stopTrace(@Nullable PrintWriter pw, boolean writeToFile) {
         if (IS_USER) {
             logAndPrintln(pw, "Error: Tracing is not supported on user builds.");
             return;
@@ -113,8 +126,10 @@
                 logAndPrintln(pw, "ERROR: tracing was re-enabled while waiting for flush.");
                 throw new IllegalStateException("tracing enabled while waiting for flush.");
             }
-            writeTraceToFileLocked();
-            logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
+            if (writeToFile) {
+                writeTraceToFileLocked();
+                logAndPrintln(pw, "Trace written to " + mTraceFile + ".");
+            }
         }
     }
 
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e8882ec..bce3e98 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -160,6 +160,8 @@
 
 using IMeasurementCorrections =
     android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+using GnssSingleSatCorrectionFlags =
+    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;
@@ -199,9 +201,7 @@
 sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
 sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 sp<IMeasurementCorrections> gnssCorrectionsIface = nullptr;
-// This boolean is needed to ensure that Gnsss Measurement Corrections related method are only
-// initalized when needed which will be few devices initially
-bool firstGnssMeasurementCorrectionInjected = false;
+
 sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
@@ -492,7 +492,7 @@
     }
 
     if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
-        SET(ElapsedUncertaintyRealtimeNanos, location.elapsedRealtime.timeUncertaintyNs);
+        SET(ElapsedRealtimeUncertaintyNanos, location.elapsedRealtime.timeUncertaintyNs);
     }
 
     return object.get();
@@ -1471,6 +1471,51 @@
             "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
     method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z");
 
+    jclass measCorrClass = env->FindClass("android/location/GnssMeasurementCorrections");
+    method_correctionsGetLatitudeDegrees = env->GetMethodID(
+            measCorrClass,"getLatitudeDegrees", "()D");
+    method_correctionsGetLongitudeDegrees = env->GetMethodID(
+            measCorrClass, "getLongitudeDegrees", "()D");
+    method_correctionsGetAltitudeMeters = env->GetMethodID(
+            measCorrClass, "getAltitudeMeters", "()D");
+    method_correctionsGetHorPosUncMeters = env->GetMethodID(
+            measCorrClass, "getHorizontalPositionUncertaintyMeters", "()D");
+    method_correctionsGetVerPosUncMeters = env->GetMethodID(
+            measCorrClass, "getVerticalPositionUncertaintyMeters", "()D");
+    method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID(
+            measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
+
+    method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
+            measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava/util/List;");
+
+    jclass corrListClass = env->FindClass("java/util/List");
+    method_listSize = env->GetMethodID(corrListClass, "size", "()I");
+    method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
+
+    jclass singleSatCorrClass = env->FindClass("android/location/GnssSingleSatCorrection");
+    method_correctionSatFlags = env->GetMethodID(
+            singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
+    method_correctionSatConstType = env->GetMethodID(
+            singleSatCorrClass, "getConstellationType", "()I");
+    method_correctionSatId= env->GetMethodID(
+            singleSatCorrClass, "getSatelliteId", "()I");
+    method_correctionSatCarrierFreq = env->GetMethodID(
+            singleSatCorrClass, "getCarrierFrequencyHz", "()F");
+    method_correctionSatIsLosProb = env->GetMethodID(
+            singleSatCorrClass,"getProbabilityLineOfSight", "()F");
+    method_correctionSatEpl = env->GetMethodID(
+            singleSatCorrClass, "getExcessPathLengthMeters", "()F");
+    method_correctionSatEplUnc = env->GetMethodID(
+            singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
+    method_correctionSatRefPlane = env->GetMethodID(
+            singleSatCorrClass, "getReflectingPlane", "()Landroid/location/GnssReflectingPlane;");
+
+    jclass refPlaneClass = env->FindClass("android/location/GnssReflectingPlane");
+    method_correctionPlaneLatDeg = env->GetMethodID(refPlaneClass, "getLatitudeDegrees", "()D");
+    method_correctionPlaneLngDeg = env->GetMethodID(refPlaneClass, "getLongitudeDegrees", "()D");
+    method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
+    method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
+
     /*
      * Save a pointer to JVM.
      */
@@ -2341,29 +2386,6 @@
         ALOGW("Trying to inject GNSS corrections on a chipset that does not support them.");
         return JNI_FALSE;
     }
-    if (firstGnssMeasurementCorrectionInjected == false) {
-        jclass measCorrClass = env->GetObjectClass(correctionsObj);
-        method_correctionsGetLatitudeDegrees = env->GetMethodID(
-            measCorrClass,"getLatitudeDegrees", "()D");
-
-        method_correctionsGetLongitudeDegrees = env->GetMethodID(
-            measCorrClass, "getLongitudeDegrees", "()D");
-
-        method_correctionsGetAltitudeMeters = env->GetMethodID(
-            measCorrClass, "getAltitudeMeters", "()D");
-
-        method_correctionsGetHorPosUncMeters = env->GetMethodID(
-            measCorrClass, "getHorizontalPositionUncertaintyMeters", "()D");
-
-        method_correctionsGetVerPosUncMeters = env->GetMethodID(
-            measCorrClass, "getVerticalPositionUncertaintyMeters", "()D");
-
-        method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID(
-            measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
-
-        method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
-            measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava.util.List;");
-    }
 
     jdouble latitudeDegreesCorr = env->CallDoubleMethod(
         correctionsObj, method_correctionsGetLatitudeDegrees);
@@ -2380,42 +2402,18 @@
     jobject singleSatCorrectionList = env->CallObjectMethod(correctionsObj,
         method_correctionsGetSingleSatCorrectionList);
 
-    if (firstGnssMeasurementCorrectionInjected == false) {
-        jclass corrListClass = env->GetObjectClass(singleSatCorrectionList);
-        method_listSize = env->GetMethodID(corrListClass, "size", "()I");
-        method_correctionListGet = env->GetMethodID(
-            corrListClass, "get", "(I)Landroid/location/GnssSingleSatCorrection;");
-    }
-
     auto len = (singleSatCorrectionList == nullptr)
         ? 0
         : env->CallIntMethod(singleSatCorrectionList, method_listSize);
+    if (len == 0) {
+        ALOGI("Empty correction list injected....Returning with no HAL injection");
+        return JNI_TRUE;
+    }
     hidl_vec<SingleSatCorrection> list(len);
 
     for (uint16_t i = 0; i < len; ++i) {
         jobject singleSatCorrectionObj = env->CallObjectMethod(
-        singleSatCorrectionList, method_correctionListGet, i);
-
-        if (firstGnssMeasurementCorrectionInjected == false) {
-            jclass singleSatCorrClass = env->GetObjectClass(singleSatCorrectionObj);
-            method_correctionSatFlags = env->GetMethodID(
-                singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
-            method_correctionSatConstType = env->GetMethodID(
-                singleSatCorrClass, "getConstellationType", "()I");
-            method_correctionSatId= env->GetMethodID(
-                singleSatCorrClass, "getSatelliteId", "()I");
-            method_correctionSatCarrierFreq = env->GetMethodID(
-                singleSatCorrClass, "getCarrierFrequencyHz", "()F");
-            method_correctionSatIsLosProb = env->GetMethodID(
-                singleSatCorrClass,"getProbabilityLineOfSight", "()F");
-            method_correctionSatEpl = env->GetMethodID(
-                singleSatCorrClass, "getExcessPathLengthMeters", "()F");
-            method_correctionSatEplUnc = env->GetMethodID(
-                singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
-            method_correctionSatRefPlane = env->GetMethodID(
-                singleSatCorrClass, "getReflectingPlane",
-                "()Landroid/location/GnssReflectingPlane;");
-        }
+            singleSatCorrectionList, method_correctionListGet, i);
 
         jint correctionFlags =
             env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
@@ -2431,38 +2429,34 @@
             env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
         jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj,
             method_correctionSatEplUnc);
-        jobject reflectingPlaneObj = env->CallObjectMethod(
-            singleSatCorrectionObj, method_correctionSatRefPlane);
-
-        if (firstGnssMeasurementCorrectionInjected == false) {
-            jclass refPlaneClass = env->GetObjectClass(reflectingPlaneObj);
-            method_correctionPlaneLatDeg = env->GetMethodID(
-                refPlaneClass, "getLatitudeDegrees", "()D");
-            method_correctionPlaneLngDeg = env->GetMethodID(
-                refPlaneClass, "getLongitudeDegrees", "()D");
-            method_correctionPlaneAltDeg = env->GetMethodID(
-                refPlaneClass, "getAltitudeMeters", "()D");
-            method_correctionPlaneAzimDeg = env->GetMethodID(
-                refPlaneClass, "getAzimuthDegrees", "()D");
+        uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
+        jobject reflectingPlaneObj;
+        bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0;
+        if (has_ref_plane) {
+            reflectingPlaneObj = env->CallObjectMethod(
+                singleSatCorrectionObj, method_correctionSatRefPlane);
         }
 
-        jdouble latitudeDegreesRefPlane = env->CallDoubleMethod(
-            reflectingPlaneObj, method_correctionPlaneLatDeg);
-        jdouble longitudeDegreesRefPlane = env->CallDoubleMethod(
-            reflectingPlaneObj, method_correctionPlaneLngDeg);
-        jdouble altitudeDegreesRefPlane = env->CallDoubleMethod(
-            reflectingPlaneObj, method_correctionPlaneAltDeg);
-        jdouble azimuthDegreeRefPlane = env->CallDoubleMethod(
-            reflectingPlaneObj, method_correctionPlaneAzimDeg);
-        ReflectingPlane reflectingPlane = {
-            .latitudeDegrees = latitudeDegreesRefPlane,
-            .longitudeDegrees = longitudeDegreesRefPlane,
-            .altitudeMeters = altitudeDegreesRefPlane,
-            .azimuthDegrees = azimuthDegreeRefPlane,
-        };
+        ReflectingPlane reflectingPlane;
+        if (has_ref_plane) {
+            jdouble latitudeDegreesRefPlane = env->CallDoubleMethod(
+                reflectingPlaneObj, method_correctionPlaneLatDeg);
+            jdouble longitudeDegreesRefPlane = env->CallDoubleMethod(
+                reflectingPlaneObj, method_correctionPlaneLngDeg);
+            jdouble altitudeDegreesRefPlane = env->CallDoubleMethod(
+                reflectingPlaneObj, method_correctionPlaneAltDeg);
+            jdouble azimuthDegreeRefPlane = env->CallDoubleMethod(
+                reflectingPlaneObj, method_correctionPlaneAzimDeg);
+            reflectingPlane = {
+                .latitudeDegrees = latitudeDegreesRefPlane,
+                .longitudeDegrees = longitudeDegreesRefPlane,
+                .altitudeMeters = altitudeDegreesRefPlane,
+                .azimuthDegrees = azimuthDegreeRefPlane,
+            };
+        }
 
         SingleSatCorrection singleSatCorrection = {
-            .singleSatCorrectionFlags = static_cast<uint16_t>(correctionFlags),
+            .singleSatCorrectionFlags = corrFlags,
             .constellation = static_cast<GnssConstellationType>(constType),
             .svid = static_cast<uint16_t>(satId),
             .carrierFrequencyHz = carrierFreqHz,
@@ -2484,7 +2478,6 @@
     };
 
     gnssCorrectionsIface->setCorrections(measurementCorrections);
-    firstGnssMeasurementCorrectionInjected = true;
     return JNI_TRUE;
 }
 
diff --git a/services/core/xsd/Android.bp b/services/core/xsd/Android.bp
new file mode 100644
index 0000000..5e1ea89
--- /dev/null
+++ b/services/core/xsd/Android.bp
@@ -0,0 +1,6 @@
+xsd_config {
+    name: "default-permissions",
+    srcs: ["default-permissions.xsd"],
+    api_dir: "schema",
+    package_name: "com.android.server.pm.permission",
+}
diff --git a/services/core/xsd/default-permissions.xsd b/services/core/xsd/default-permissions.xsd
new file mode 100644
index 0000000..d800a26
--- /dev/null
+++ b/services/core/xsd/default-permissions.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="exceptions">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="exception" type="exception" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:complexType name="exception">
+        <xs:sequence>
+            <xs:element name="permission" type="permission"/>
+        </xs:sequence>
+        <xs:attribute name="package" type="xs:string"/>
+        <xs:attribute name="sha256-cert-digest" type="xs:string"/>
+        <xs:attribute name="brand" type="xs:string"/>
+    </xs:complexType>
+    <xs:complexType name="permission">
+        <xs:attribute name="name" type="xs:string"/>
+        <xs:attribute name="fixed" type="xs:boolean"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/services/core/xsd/schema/README.md b/services/core/xsd/schema/README.md
new file mode 100644
index 0000000..f52d93d
--- /dev/null
+++ b/services/core/xsd/schema/README.md
@@ -0,0 +1 @@
+Please see the [README](https://android.googlesource.com/platform/system/tools/xsdc/+/refs/heads/master/README.md) for details regarding the Configfile as API.
diff --git a/services/core/xsd/schema/current.txt b/services/core/xsd/schema/current.txt
new file mode 100644
index 0000000..4e67e5c
--- /dev/null
+++ b/services/core/xsd/schema/current.txt
@@ -0,0 +1,37 @@
+// Signature format: 2.0
+package com.android.server.pm.permission {
+
+  public class Exception {
+    ctor public Exception();
+    method public String getBrand();
+    method public com.android.server.pm.permission.Permission getPermission();
+    method public String getSha256CertDigest();
+    method public String get_package();
+    method public void setBrand(String);
+    method public void setPermission(com.android.server.pm.permission.Permission);
+    method public void setSha256CertDigest(String);
+    method public void set_package(String);
+  }
+
+  public class Exceptions {
+    ctor public Exceptions();
+    method public java.util.List<com.android.server.pm.permission.Exception> getException();
+  }
+
+  public class Permission {
+    ctor public Permission();
+    method public boolean getFixed();
+    method public String getName();
+    method public void setFixed(boolean);
+    method public void setName(String);
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static com.android.server.pm.permission.Exceptions read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/services/core/xsd/schema/last_current.txt b/services/core/xsd/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/core/xsd/schema/last_current.txt
diff --git a/services/core/xsd/schema/last_removed.txt b/services/core/xsd/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/core/xsd/schema/last_removed.txt
diff --git a/services/core/xsd/schema/removed.txt b/services/core/xsd/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/services/core/xsd/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f496e81..36251f5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -172,7 +172,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
-import android.os.ParcelableException;
 import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
@@ -5338,9 +5337,14 @@
      */
     @Override
     public long getRequiredStrongAuthTimeout(ComponentName who, int userId, boolean parent) {
-        if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
+        if (!mHasFeature) {
             return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
         }
+        if (!mLockPatternUtils.hasSecureLockScreen()) {
+            // No strong auth timeout on devices not supporting the
+            // {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature
+            return 0;
+        }
         enforceFullCrossUsersPermission(userId);
         synchronized (getLockObject()) {
             if (who != null) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a19d5d5..eba00812 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1881,19 +1881,6 @@
         mSystemServiceManager.startService(IncidentCompanionService.class);
         traceEnd();
 
-        if (safeMode) {
-            traceBeginAndSlog("EnterSafeModeAndDisableJitCompilation");
-            mActivityManagerService.enterSafeMode();
-            // Disable the JIT for the system_server process
-            VMRuntime.getRuntime().disableJitCompilation();
-            traceEnd();
-        } else {
-            // Enable the JIT for the system_server process
-            traceBeginAndSlog("StartJitCompilation");
-            VMRuntime.getRuntime().startJitCompilation();
-            traceEnd();
-        }
-
         // MMS service broker
         traceBeginAndSlog("StartMmsService");
         mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 16f72bd..4240d24 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -109,7 +109,7 @@
     }
 
     public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException {
-        SocketUtils.connectSocket(fd, makeNetlinkSocketAddress(0, 0));
+        Os.connect(fd, makeNetlinkSocketAddress(0, 0));
     }
 
     private static void checkTimeout(long timeoutMs) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index c8e6782..d0158e0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -685,10 +685,10 @@
         List<OpEntry> entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_IGNORED));
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_IGNORED));
 
         ops.add(new PackageOps(PACKAGE_1, UID_1, entries));
 
@@ -696,7 +696,7 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_IGNORED));
 
         ops.add(new PackageOps(PACKAGE_2, UID_2, entries));
 
@@ -704,7 +704,7 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_ALLOWED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_ALLOWED));
 
         ops.add(new PackageOps(PACKAGE_1, UID_10_1, entries));
 
@@ -712,10 +712,10 @@
         entries = new ArrayList<>();
         entries.add(new OpEntry(
                 AppStateTracker.TARGET_OP,
-                AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_IGNORED));
         entries.add(new OpEntry(
                 AppOpsManager.OP_ACCESS_NOTIFICATIONS,
-                AppOpsManager.MODE_IGNORED, 0, 0, 0, 0, null));
+                AppOpsManager.MODE_IGNORED));
 
         ops.add(new PackageOps(PACKAGE_3, UID_10_3, entries));
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index b13735c..0d6020c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -35,9 +35,12 @@
 import android.os.RecoverySystem;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.am.SettingsToPropertiesMapper;
+import com.android.server.utils.FlagNamespaceUtils;
 
 import org.junit.After;
 import org.junit.Before;
@@ -56,6 +59,10 @@
 public class RescuePartyTest {
     private static final int PERSISTENT_APP_UID = 12;
     private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
+    private static final String FAKE_NATIVE_NAMESPACE1 = "native1";
+    private static final String FAKE_NATIVE_NAMESPACE2 = "native2";
+    private static final String[] FAKE_RESET_NATIVE_NAMESPACES =
+            {FAKE_NATIVE_NAMESPACE1, FAKE_NATIVE_NAMESPACE2};
 
     private MockitoSession mSession;
 
@@ -73,9 +80,11 @@
                 ExtendedMockito.mockitoSession().initMocks(
                         this)
                         .strictness(Strictness.LENIENT)
+                        .spyStatic(DeviceConfig.class)
                         .spyStatic(SystemProperties.class)
                         .spyStatic(Settings.Global.class)
                         .spyStatic(Settings.Secure.class)
+                        .spyStatic(SettingsToPropertiesMapper.class)
                         .spyStatic(RecoverySystem.class)
                         .spyStatic(RescueParty.class)
                         .startMocking();
@@ -121,8 +130,17 @@
                 }
         ).when(() -> SystemProperties.getLong(anyString(), anyLong()));
 
+        // Mock DeviceConfig
+        doAnswer((Answer<Boolean>) invocationOnMock -> true)
+                .when(() -> DeviceConfig.setProperty(anyString(), anyString(), anyString(),
+                        anyBoolean()));
+        doAnswer((Answer<Void>) invocationOnMock -> null)
+                .when(() -> DeviceConfig.resetToDefaults(anyInt(), anyString()));
+
+
         doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
         RescueParty.resetAllThresholds();
+        FlagNamespaceUtils.resetKnownResetNamespacesFlagCounterForTest();
 
         SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL,
                 Integer.toString(RescueParty.LEVEL_NONE));
@@ -278,10 +296,32 @@
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
     }
 
+    @Test
+    public void testNativeRescuePartyResets() {
+        doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed());
+        doReturn(FAKE_RESET_NATIVE_NAMESPACES).when(
+                () -> SettingsToPropertiesMapper.getResetNativeCategories());
+
+        RescueParty.onSettingsProviderPublished(mMockContext);
+
+        verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
+                FAKE_NATIVE_NAMESPACE1));
+        verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
+                FAKE_NATIVE_NAMESPACE2));
+
+        ExtendedMockito.verify(
+                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
+                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 0,
+                        FAKE_NATIVE_NAMESPACE1, /*makeDefault=*/true));
+        ExtendedMockito.verify(
+                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
+                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 1,
+                        FAKE_NATIVE_NAMESPACE2, /*makeDefault=*/true));
+    }
+
     private void verifySettingsResets(int resetMode) {
         verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
-                resetMode,
-                UserHandle.USER_SYSTEM));
+                resetMode, UserHandle.USER_SYSTEM));
         verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
                 eq(resetMode), anyInt()));
     }
@@ -294,7 +334,7 @@
 
     private void notePersistentAppCrash(int numTimes) {
         for (int i = 0; i < numTimes; i++) {
-            RescueParty.notePersistentAppCrash(mMockContext, PERSISTENT_APP_UID);
+            RescueParty.noteAppCrash(mMockContext, PERSISTENT_APP_UID);
         }
     }
 }
diff --git a/services/tests/runtests.py b/services/tests/runtests.py
index f19cc5d..4c8b4ba 100755
--- a/services/tests/runtests.py
+++ b/services/tests/runtests.py
@@ -19,7 +19,7 @@
 import sys
 
 INSTRUMENTED_PACKAGE_RUNNER = ('com.android.frameworks.servicestests/'
-                               'android.support.test.runner.AndroidJUnitRunner')
+                               'androidx.test.runner.AndroidJUnitRunner')
 
 PACKAGE_WHITELIST = (
     "com.android.server",
diff --git a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
new file mode 100644
index 0000000..5b85980
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
@@ -0,0 +1,160 @@
+/*
+ * 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.am;
+
+import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.FlakyTest;
+
+import com.android.server.wm.ActivityTaskManagerService;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.Collections;
+
+/**
+ * Build/Install/Run:
+ *  atest FrameworksServicesTests:ProcessRecordTests
+ */
+@Presubmit
+@FlakyTest(detail = "Promote to presubmit when shown to be stable.")
+public class ProcessRecordTests {
+    private static Context sContext;
+    private static ActivityManagerService sService;
+
+    private ProcessRecord mProcessRecord;
+
+    @BeforeClass
+    public static void setUpOnce() throws Exception {
+        sContext = getInstrumentation().getTargetContext();
+
+        // We need to run with dexmaker share class loader to make use of ActivityTaskManagerService
+        // from wm package.
+        runWithDexmakerShareClassLoader(() -> {
+            sService = mock(ActivityManagerService.class);
+            sService.mActivityTaskManager = new ActivityTaskManagerService(sContext);
+            sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper());
+            sService.mAtmInternal = sService.mActivityTaskManager.getAtmInternal();
+        });
+    }
+
+    @Before
+    public void setUpProcess() throws Exception {
+        // Need to run with dexmaker share class loader to mock package private class.
+        runWithDexmakerShareClassLoader(() -> {
+            mProcessRecord = spy(new ProcessRecord(sService, sContext.getApplicationInfo(),
+                    "name", 12345));
+            doNothing().when(mProcessRecord).startAppProblemLocked();
+            doReturn(false).when(mProcessRecord).isSilentAnr();
+            doReturn(false).when(mProcessRecord).isMonitorCpuUsage();
+            doReturn(Collections.emptyList()).when(mProcessRecord).getLruProcessList();
+        });
+    }
+
+
+    /**
+     * This test verifies the process default status. If this doesn't pass, none of the other tests
+     * should be able to pass.
+     */
+    @Test
+    public void testProcessDefaultAnrRelatedStatus() {
+        assertFalse(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.isCrashing());
+        assertFalse(mProcessRecord.killedByAm);
+        assertFalse(mProcessRecord.killed);
+    }
+
+    /**
+     * This test verifies that if the process is crashing, Anr will do nothing.
+     */
+    @Test
+    public void testAnrWhenCrash() {
+        mProcessRecord.setCrashing(true);
+        assertTrue(mProcessRecord.isCrashing());
+        mProcessRecord.appNotResponding(null, null, null, null, false, "Test ANR when crash");
+        assertFalse(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.killedByAm);
+        assertFalse(mProcessRecord.killed);
+    }
+
+    /**
+     * This test verifies that if the process is killed by AM, Anr will do nothing.
+     */
+    @Test
+    public void testAnrWhenKilledByAm() {
+        mProcessRecord.killedByAm = true;
+        mProcessRecord.appNotResponding(null, null, null, null, false,
+                "Test ANR when killed by AM");
+        assertFalse(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.isCrashing());
+        assertFalse(mProcessRecord.killed);
+    }
+
+    /**
+     * This test verifies that if the process is killed, Anr will do nothing.
+     */
+    @Test
+    public void testAnrWhenKilled() {
+        mProcessRecord.killed = true;
+        mProcessRecord.appNotResponding(null, null, null, null, false, "Test ANR when killed");
+        assertFalse(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.isCrashing());
+        assertFalse(mProcessRecord.killedByAm);
+    }
+
+    /**
+     * This test verifies that non-silent ANR can run through successfully and the corresponding
+     * flags can be set correctly.
+     */
+    @Test
+    public void testNonSilentAnr() {
+        mProcessRecord.appNotResponding(null, null, null, null, false, "Test non-silent ANR");
+        assertTrue(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.isCrashing());
+        assertFalse(mProcessRecord.killedByAm);
+        assertFalse(mProcessRecord.killed);
+    }
+
+    /**
+     * This test verifies that silent ANR can run through successfully and the corresponding flags
+     * can be set correctly.
+     */
+    @Test
+    public void testSilentAnr() {
+        // Silent Anr will run through even without a parent process, and directly killed by AM.
+        doReturn(true).when(mProcessRecord).isSilentAnr();
+        mProcessRecord.appNotResponding(null, null, null, null, false, "Test silent ANR");
+        assertTrue(mProcessRecord.isNotResponding());
+        assertFalse(mProcessRecord.isCrashing());
+        assertTrue(mProcessRecord.killedByAm);
+        assertTrue(mProcessRecord.killed);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index edd89f9..96f329b 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -45,21 +45,6 @@
 
     private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
 
-    public void testWatchNotedOpsRequiresPermission() {
-        // Create a mock listener
-        final OnOpNotedListener listener = mock(OnOpNotedListener.class);
-
-        // Try to start watching noted ops
-        final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
-        try {
-            appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
-                    AppOpsManager.OP_RECORD_AUDIO}, listener);
-            fail("Watching noted ops shoudl require " + Manifest.permission.WATCH_APPOPS);
-        } catch (SecurityException expected) {
-            /*ignored*/
-        }
-    }
-
     @Test
     public void testWatchNotedOps() {
         // Create a mock listener
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index eb0c627..66d2bab 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -107,8 +107,8 @@
                 }
                 final AppOpsService.Op _op1 = ops.get(op1);
                 final AppOpsService.Op _op2 = ops.get(op2);
-                final int mode1 = (_op1 == null) ? defaultModeOp1 : _op1.mode;
-                final int mode2 = (_op2 == null) ? defaultModeOp2 : _op2.mode;
+                final int mode1 = (_op1 == null) ? defaultModeOp1 : _op1.getMode();
+                final int mode2 = (_op2 == null) ? defaultModeOp2 : _op2.getMode();
                 assertEquals(mode1, mode2);
                 if (mode1 != defaultModeOp1) {
                     numberOfNonDefaultOps++;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index c78b96d..5bab65c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -59,6 +59,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.locksettings.recoverablekeystore.storage.ApplicationKeyStorage;
+import com.android.server.locksettings.recoverablekeystore.storage.CleanupManager;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
@@ -154,6 +155,7 @@
     @Mock private KeyguardManager mKeyguardManager;
     @Mock private PlatformKeyManager mPlatformKeyManager;
     @Mock private ApplicationKeyStorage mApplicationKeyStorage;
+    @Mock private CleanupManager mCleanupManager;
     @Spy private TestOnlyInsecureCertificateHelper mTestOnlyInsecureCertificateHelper;
 
     private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
@@ -191,7 +193,8 @@
                 mMockListenersStorage,
                 mPlatformKeyManager,
                 mApplicationKeyStorage,
-                mTestOnlyInsecureCertificateHelper);
+                mTestOnlyInsecureCertificateHelper,
+                mCleanupManager);
     }
 
     @After
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/CleanupManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/CleanupManagerTest.java
new file mode 100644
index 0000000..0b15a12
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/CleanupManagerTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.locksettings.recoverablekeystore.storage;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CleanupManagerTest {
+    private static final int USER_ID = 10;
+    private static final int USER_ID_2 = 20;
+    private static final int UID = 1234;
+    private static final long USER_SERIAL_NUMBER = 101L;
+    private static final long USER_SERIAL_NUMBER_2 = 202L;
+
+    private Context mContext;
+    private CleanupManager mManager;
+
+    @Mock private RecoverableKeyStoreDb mDatabase;
+    @Mock private RecoverySnapshotStorage mRecoverySnapshotStorage;
+    @Mock private UserManager mUserManager;
+    @Mock private ApplicationKeyStorage mApplicationKeyStorage;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = InstrumentationRegistry.getTargetContext();
+        mManager = new CleanupManager(mContext, mRecoverySnapshotStorage, mDatabase, mUserManager,
+                mApplicationKeyStorage);
+    }
+
+    @Test
+    public void registerRecoveryAgent_unknownUser_storesInDb() throws Exception {
+        when(mDatabase.getUserSerialNumbers()).thenReturn(new HashMap<>());
+        when(mUserManager.getSerialNumberForUser(eq(UserHandle.of(USER_ID))))
+                .thenReturn(USER_SERIAL_NUMBER);
+        when(mUserManager.getSerialNumberForUser(eq(UserHandle.of(USER_ID_2))))
+                .thenReturn(USER_SERIAL_NUMBER_2);
+
+        mManager.registerRecoveryAgent(USER_ID, UID);
+        mManager.registerRecoveryAgent(USER_ID_2, UID);
+
+        verify(mDatabase).setUserSerialNumber(USER_ID, USER_SERIAL_NUMBER);
+        verify(mDatabase).setUserSerialNumber(USER_ID_2, USER_SERIAL_NUMBER_2);
+
+    }
+
+    @Test
+    public void registerRecoveryAgent_registersSameUser_doesntChangeDb() throws Exception {
+        when(mDatabase.getUserSerialNumbers()).thenReturn(new HashMap<>());
+        when(mUserManager.getSerialNumberForUser(eq(UserHandle.of(USER_ID))))
+                .thenReturn(USER_SERIAL_NUMBER);
+
+        mManager.registerRecoveryAgent(USER_ID, UID);
+        mManager.registerRecoveryAgent(USER_ID, UID); // ignored.
+
+        verify(mDatabase, times(1)).setUserSerialNumber(USER_ID, USER_SERIAL_NUMBER);
+    }
+
+    @Test
+    public void verifyKnownUsers_newSerialNumber_deletesData() throws Exception {
+        Map knownSerialNumbers = new HashMap<>();
+        knownSerialNumbers.put(USER_ID, USER_SERIAL_NUMBER);
+        when(mDatabase.getUserSerialNumbers()).thenReturn(knownSerialNumbers);
+        List<Integer> recoveryAgents = new ArrayList<>();
+        recoveryAgents.add(UID);
+        when(mDatabase.getRecoveryAgents(USER_ID)).thenReturn(recoveryAgents);
+
+        when(mUserManager.getSerialNumberForUser(eq(UserHandle.of(USER_ID))))
+                .thenReturn(USER_SERIAL_NUMBER_2); // new value
+
+
+        mManager.verifyKnownUsers();
+
+        verify(mDatabase).removeUserFromAllTables(USER_ID);
+        verify(mDatabase).setUserSerialNumber(USER_ID, USER_SERIAL_NUMBER_2);
+        verify(mRecoverySnapshotStorage).remove(UID);
+    }
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
index 35215c3..2658af6 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java
@@ -51,6 +51,7 @@
     private static final long TEST_LAST_SYNCED_AT = 1517990732000L;
     private static final int TEST_RECOVERY_STATUS = 3;
     private static final int TEST_PLATFORM_KEY_GENERATION_ID = 11;
+    private static final int TEST_USER_SERIAL_NUMBER = 15;
     private static final int TEST_SNAPSHOT_VERSION = 31;
     private static final int TEST_SHOULD_CREATE_SNAPSHOT = 1;
     private static final byte[] TEST_PUBLIC_KEY = "test-public-key".getBytes(UTF_8);
@@ -234,5 +235,14 @@
 
         assertThat(mDatabase.replace(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
                 .isGreaterThan(-1L);
+
+        // User serial number column was added when upgrading from v5 to v6
+        values = new ContentValues();
+        values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID);
+        values.put(UserMetadataEntry.COLUMN_NAME_USER_SERIAL_NUMBER, TEST_USER_SERIAL_NUMBER);
+        assertThat(
+                mDatabase.replace(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values))
+                .isGreaterThan(-1L);
     }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 7de9ffc..932a769 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -279,6 +279,55 @@
     }
 
     @Test
+    public void getUserSerialNumbers_returnsSerialNumbers() {
+        int userId = 42;
+        int userId2 = 44;
+        Long serialNumber = 24L;
+        Long serialNumber2 = 25L;
+        mRecoverableKeyStoreDb.setUserSerialNumber(userId, serialNumber);
+        mRecoverableKeyStoreDb.setUserSerialNumber(userId2, serialNumber2);
+
+        assertEquals(2, mRecoverableKeyStoreDb.getUserSerialNumbers().size());
+        assertEquals(serialNumber, mRecoverableKeyStoreDb.getUserSerialNumbers().get(userId));
+        assertEquals(serialNumber2, mRecoverableKeyStoreDb.getUserSerialNumbers().get(userId2));
+    }
+
+    @Test
+    public void getUserSerialNumbers_returnsMinusOneIfNoEntry() {
+        int userId = 42;
+        int generationId = 24;
+        Long serialNumber = -1L;
+        // Don't set serial number
+        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId);
+
+        assertEquals(1, mRecoverableKeyStoreDb.getUserSerialNumbers().size());
+        assertEquals(serialNumber, mRecoverableKeyStoreDb.getUserSerialNumbers().get(userId));
+    }
+
+    @Test
+    public void removeUserFromAllTables_removesData() throws Exception {
+        int userId = 12;
+        int generationId = 24;
+        int[] types = new int[]{1};
+        int uid = 10009;
+        mRecoverableKeyStoreDb.setRecoveryServiceCertSerial(userId, uid,
+                TEST_ROOT_CERT_ALIAS, 1234L);
+        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(userId, generationId);
+        mRecoverableKeyStoreDb.setActiveRootOfTrust(userId, uid, "root");
+        mRecoverableKeyStoreDb.setRecoverySecretTypes(userId, uid, types);
+
+        mRecoverableKeyStoreDb.removeUserFromAllTables(userId);
+
+        // RootOfTrust
+        assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
+                TEST_ROOT_CERT_ALIAS)).isNull();
+        // UserMetadata
+        assertThat(mRecoverableKeyStoreDb.getPlatformKeyGenerationId(userId)).isEqualTo(-1);
+        // RecoveryServiceMetadata
+        assertThat(mRecoverableKeyStoreDb.getRecoverySecretTypes(userId, uid)).isEmpty();
+    }
+
+    @Test
     public void setRecoveryStatus_withSingleKey() {
         int userId = 12;
         int uid = 1009;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 72357ce..3c3721c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.pm;
 
+import static android.content.res.Resources.ID_NULL;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
@@ -453,8 +455,8 @@
         pkg.splitPrivateFlags = new int[] { 100 };
         pkg.applicationInfo = new ApplicationInfo();
 
-        pkg.permissions.add(new PackageParser.Permission(pkg));
-        pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg));
+        pkg.permissions.add(new PackageParser.Permission(pkg, (String) null));
+        pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg, ID_NULL, ID_NULL, ID_NULL));
 
         final PackageParser.ParseComponentArgs dummy = new PackageParser.ParseComponentArgs(
                 pkg, new String[1], 0, 0, 0, 0, 0, 0, null, 0, 0, 0);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 8caa39d..1f86171 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -175,9 +175,9 @@
     /** Verify app usage limit observer is added */
     @Test
     public void testAppUsageLimitObserver_AddObserver() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
-        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID2));
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
     }
@@ -203,7 +203,7 @@
     /** Verify app usage limit observer is removed */
     @Test
     public void testAppUsageLimitObserver_RemoveObserver() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
         assertFalse("Observer wasn't removed", hasAppUsageLimitObserver(UID, OBS_ID1));
@@ -290,9 +290,9 @@
     /** Re-adding an observer should result in only one copy */
     @Test
     public void testAppUsageLimitObserver_ObserverReAdd() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN);
         assertTrue("Observer wasn't added",
                 getAppUsageLimitObserver(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
         mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID);
@@ -304,7 +304,7 @@
     public void testAllObservers_ExclusiveObserverIds() {
         addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
         addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN);
         assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
         assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1));
@@ -396,7 +396,7 @@
     @Test
     public void testAppUsageLimitObserver_Accumulation() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         startUsage(PKG_SOC1);
         // Add 10 mins
         setTime(TIME_10_MIN);
@@ -456,7 +456,7 @@
     @Test
     public void testAppUsageLimitObserver_TimeoutOtherApp() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L);
         startUsage(PKG_SOC2);
         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
         setTime(6_000L);
@@ -498,7 +498,7 @@
     @Test
     public void testAppUsageLimitObserver_Timeout() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L);
         startUsage(PKG_SOC1);
         setTime(6_000L);
         assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
@@ -551,7 +551,7 @@
         setTime(TIME_10_MIN);
         startUsage(PKG_GAME1);
         setTime(TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN);
         setTime(TIME_30_MIN + TIME_10_MIN);
         stopUsage(PKG_GAME1);
         assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
@@ -612,7 +612,7 @@
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         // 10 second time limit
-        addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L);
+        addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L, 10_000L);
         setTime(TIME_10_MIN + 5_000L);
         // Shouldn't call back in 6 seconds
         assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
@@ -692,23 +692,23 @@
     public void testAppUsageLimitObserver_MaxObserverLimit() throws Exception {
         boolean receivedException = false;
         int ANOTHER_UID = UID + 1;
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN, TIME_30_MIN);
         // Readding an observer should not cause an IllegalStateException
-        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN);
         // Adding an observer for a different uid shouldn't cause an IllegalStateException
         mController.addAppUsageLimitObserver(
-                ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID);
+                ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN, null, USER_ID);
         try {
-            addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN);
+            addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN);
         } catch (IllegalStateException ise) {
             receivedException = true;
         }
@@ -748,9 +748,9 @@
     public void testAppUsageLimitObserver_MinimumTimeLimit() throws Exception {
         boolean receivedException = false;
         // adding an observer with a one minute time limit should not cause an exception
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT, MIN_TIME_LIMIT);
         try {
-            addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1);
+            addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1, MIN_TIME_LIMIT - 1);
         } catch (IllegalArgumentException iae) {
             receivedException = true;
         }
@@ -807,7 +807,7 @@
     @Test
     public void testAppUsageLimitObserver_ConcurrentUsage() throws Exception {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         AppTimeLimitController.UsageGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         startUsage(PKG_SOC1);
         // Add 10 mins
@@ -967,7 +967,7 @@
     /** Verify app usage limit observer added correctly reports its total usage limit */
     @Test
     public void testAppUsageLimitObserver_GetTotalUsageLimit() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         assertNotNull("Observer wasn't added", group);
         assertEquals("Observer didn't correctly report total usage limit",
@@ -978,7 +978,7 @@
     @Test
     public void testAppUsageLimitObserver_GetUsageRemaining() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         stopUsage(PKG_SOC1);
@@ -993,8 +993,8 @@
      */
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimit() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
         UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1);
         assertEquals("Observer with the smallest usage limit remaining wasn't returned",
                 TIME_10_MIN, group.getTotalUsageLimit());
@@ -1006,8 +1006,8 @@
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimitUsed() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
         startUsage(PKG_GAME1);
         setTime(TIME_10_MIN * 2 + TIME_1_MIN);
         stopUsage(PKG_GAME1);
@@ -1024,8 +1024,8 @@
     @Test
     public void testAppUsageLimitObserver_GetAppUsageLimitAllUsed() {
         setTime(0L);
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN);
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN);
+        addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN);
         startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         stopUsage(PKG_SOC1);
@@ -1035,10 +1035,21 @@
                 0L, group.getUsageRemaining());
     }
 
+    /** Verify that a limit of 0 is not allowed. */
+    @Test
+    public void testAppUsageLimitObserver_ZeroTimeLimitIsNotAllowed() {
+        try {
+            addAppUsageLimitObserver(OBS_ID1, GROUP1, 0, 0);
+            fail("timeLimit of 0 should not be allowed.");
+        } catch (IllegalArgumentException expected) {
+            // Exception expected.
+        }
+    }
+
     /** Verify that a limit of 0 is allowed for the special case of re-registering an observer. */
     @Test
-    public void testAppUsageLimitObserver_ZeroTimeLimitIsAllowed() {
-        addAppUsageLimitObserver(OBS_ID1, GROUP1, 0);
+    public void testAppUsageLimitObserver_ZeroTimeRemainingIsAllowed() {
+        addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_1_MIN, 0);
         AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1);
         assertNotNull("Observer wasn't added", group);
         assertEquals("Usage remaining was not 0.", 0, group.getUsageRemaining());
@@ -1066,8 +1077,10 @@
                 null, null, USER_ID);
     }
 
-    private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit) {
-        mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, null, USER_ID);
+    private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit,
+            long timeRemaining) {
+        mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, timeRemaining,
+                null, USER_ID);
     }
 
     /** Is there still an app usage observer by that id */
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index e36586e..2077ecb 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -36,6 +36,7 @@
 import android.app.Instrumentation;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.LocusId;
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.Callback;
 import android.content.pm.ShortcutInfo;
@@ -369,6 +370,10 @@
         return ret;
     }
 
+    public static LocusId locusId(String id) {
+        return new LocusId(id);
+    }
+
     public static void resetAll(Collection<?> mocks) {
         for (Object o : mocks) {
             reset(o);
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index e4ab257..92198fa 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -22,6 +22,7 @@
         "platform-test-annotations",
         "hamcrest-library",
         "testables",
+        "truth-prebuilt",
     ],
 
     libs: [
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 7a530df..43fe674 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -1228,5 +1228,10 @@
         protected void onServiceAdded(ManagedServiceInfo info) {
 
         }
+
+        @Override
+        protected String getRequiredPermission() {
+            return null;
+        }
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index 19b567f..88186cd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -114,10 +114,10 @@
 
     @Test
     public void testXmlUpgrade() {
-        mAssistants.ensureAssistant();
+        mAssistants.resetDefaultAssistantsIfNecessary();
 
         //once per user
-        verify(mNm, times(mUm.getUsers().size())).readDefaultAssistant(anyInt());
+        verify(mNm, times(mUm.getUsers().size())).setDefaultAssistantForUser(anyInt());
     }
 
     @Test
@@ -132,7 +132,7 @@
         parser.nextTag();
         mAssistants.readXml(parser, null, false, UserHandle.USER_ALL);
 
-        verify(mNm, never()).readDefaultAssistant(anyInt());
+        verify(mNm, never()).setDefaultAssistantForUser(anyInt());
         verify(mAssistants, times(1)).addApprovedList(
                 new ComponentName("b", "b").flattenToString(),10, true);
     }
@@ -143,13 +143,13 @@
         ComponentName component2 = ComponentName.unflattenFromString("package/Component2");
         mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
                 true);
-        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
-                eq(mZero.id), anyBoolean());
+        verify(mNm, never()).setNotificationAssistantAccessGrantedForUserInternal(
+                any(ComponentName.class), eq(mZero.id), anyBoolean());
 
         mAssistants.setPackageOrComponentEnabled(component2.flattenToString(), mZero.id, true,
                 true);
-        verify(mINm, times(1)).setNotificationAssistantAccessGrantedForUser(component1, mZero.id,
-                false);
+        verify(mNm, times(1)).setNotificationAssistantAccessGrantedForUserInternal(
+                component1, mZero.id, false);
     }
 
     @Test
@@ -159,7 +159,7 @@
                 true);
         mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
                 true);
-        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
-                eq(mZero.id), anyBoolean());
+        verify(mNm, never()).setNotificationAssistantAccessGrantedForUserInternal(
+                any(ComponentName.class), eq(mZero.id), anyBoolean());
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 31788ae..7df52b2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -98,7 +98,9 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.provider.MediaStore;
+import android.provider.Settings;
 import android.service.notification.Adjustment;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
@@ -111,9 +113,13 @@
 import android.testing.TestableLooper.RunWithLooper;
 import android.text.Html;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.AtomicFile;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.R;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -142,6 +148,7 @@
 import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -153,6 +160,13 @@
 @RunWithLooper
 public class NotificationManagerServiceTest extends UiServiceTestCase {
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
+    private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
+            "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
+                    + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
+    private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD =
+            "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
+                    + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
+
     private final int mUid = Binder.getCallingUid();
     private TestableNotificationManagerService mService;
     private INotificationManager mBinderService;
@@ -208,6 +222,9 @@
     AppOpsManager mAppOpsManager;
     @Mock
     private UserManagerService mUserMangerService;
+    @Mock
+    private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
+            mNotificationAssistantAccessGrantedCallback;
 
     // Use a Testable subclass so we can simulate calls from the system without failing.
     private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -215,6 +232,8 @@
         boolean isSystemUid = true;
         int countLogSmartSuggestionsVisible = 0;
         UserManagerService mUserManagerService;
+        @Nullable
+        NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
 
         TestableNotificationManagerService(Context context, UserManagerService userManagerService) {
             super(context);
@@ -258,6 +277,26 @@
         UserManagerService getUserManagerService() {
             return mUserManagerService;
         }
+
+        @Override
+        protected void setNotificationAssistantAccessGrantedForUserInternal(
+                ComponentName assistant, int userId, boolean granted) {
+            if (mNotificationAssistantAccessGrantedCallback != null) {
+                mNotificationAssistantAccessGrantedCallback.onGranted(assistant, userId, granted);
+                return;
+            }
+            super.setNotificationAssistantAccessGrantedForUserInternal(assistant, userId, granted);
+        }
+
+        private void setNotificationAssistantAccessGrantedCallback(
+                @Nullable NotificationAssistantAccessGrantedCallback callback) {
+            this.mNotificationAssistantAccessGrantedCallback = callback;
+        }
+
+        interface NotificationAssistantAccessGrantedCallback {
+            void onGranted(ComponentName assistant, int userId, boolean granted);
+        }
+
     }
 
     private class TestableToastCallback extends ITransientNotification.Stub {
@@ -352,6 +391,7 @@
     @After
     public void tearDown() throws Exception {
         mFile.delete();
+        clearDeviceConfig();
     }
 
     public void waitForIdle() {
@@ -2029,6 +2069,7 @@
         verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
         verify(mAssistants, times(1)).setPackageOrComponentEnabled(
                 c.flattenToString(), user.getIdentifier(), true, true);
+        verify(mAssistants).setUserSet(10, true);
         verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
                 c.flattenToString(), user.getIdentifier(), false, true);
         verify(mListeners, never()).setPackageOrComponentEnabled(
@@ -2518,7 +2559,7 @@
         verify(mListeners, times(1)).migrateToXml();
         verify(mConditionProviders, times(1)).migrateToXml();
         verify(mAssistants, times(1)).migrateToXml();
-        verify(mAssistants, never()).ensureAssistant();
+        verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
@@ -2538,7 +2579,7 @@
         verify(mListeners, times(2)).migrateToXml();
         verify(mConditionProviders, times(2)).migrateToXml();
         verify(mAssistants, times(2)).migrateToXml();
-        verify(mAssistants, never()).ensureAssistant();
+        verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
@@ -3619,7 +3660,7 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(false, mService.canUseManagedServices(null));
+        assertEquals(false, mService.canUseManagedServices(null, 0, null));
     }
 
     @Test
@@ -3630,7 +3671,7 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(true, mService.canUseManagedServices("b"));
+        assertEquals(true, mService.canUseManagedServices("b", 0, null));
     }
 
     @Test
@@ -3641,7 +3682,7 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(false, mService.canUseManagedServices("d"));
+        assertEquals(false, mService.canUseManagedServices("d", 0, null));
     }
 
     @Test
@@ -3652,7 +3693,7 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(true, mService.canUseManagedServices("d"));
+        assertEquals(true, mService.canUseManagedServices("d", 0, null));
     }
 
     @Test
@@ -3663,7 +3704,7 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(true, mService.canUseManagedServices("d"));
+        assertEquals(true, mService.canUseManagedServices("d", 0 , null));
     }
 
     @Test
@@ -3674,7 +3715,28 @@
                 .thenReturn(new String[] {"a", "b", "c"});
         when(mContext.getResources()).thenReturn(mResources);
 
-        assertEquals(true, mService.canUseManagedServices("d"));
+        assertEquals(true, mService.canUseManagedServices("d", 0, null));
+    }
+
+    @Test
+    public void testCanUseManagedServices_hasPermission() throws Exception {
+        when(mPackageManager.checkPermission("perm", "pkg", 0))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+
+        assertEquals(true, mService.canUseManagedServices("pkg", 0, "perm"));
+    }
+
+    @Test
+    public void testCanUseManagedServices_noPermission() throws Exception {
+        when(mPackageManager.checkPermission("perm", "pkg", 0))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+
+        assertEquals(false, mService.canUseManagedServices("pkg", 0, "perm"));
+    }
+
+    @Test
+    public void testCanUseManagedServices_permDoesNotMatter() {
+        assertEquals(true, mService.canUseManagedServices("pkg", 0, null));
     }
 
     @Test
@@ -4101,4 +4163,78 @@
         verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
         assertNotNull(captor.getValue());
     }
+
+    @Test
+    public void setDefaultAssistantForUser_fromConfigXml() {
+        clearDeviceConfig();
+        ComponentName xmlConfig = new ComponentName("config", "xml");
+        when(mResources
+                .getString(
+                        com.android.internal.R.string.config_defaultAssistantAccessComponent))
+                .thenReturn(xmlConfig.flattenToString());
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
+                .thenReturn(Collections.singleton(xmlConfig));
+        mService.setNotificationAssistantAccessGrantedCallback(
+                mNotificationAssistantAccessGrantedCallback);
+
+        mService.setDefaultAssistantForUser(0);
+
+        verify(mNotificationAssistantAccessGrantedCallback)
+                .onGranted(eq(xmlConfig), eq(0), eq(true));
+    }
+
+    @Test
+    public void setDefaultAssistantForUser_fromDeviceConfig() {
+        ComponentName xmlConfig = new ComponentName("xml", "config");
+        ComponentName deviceConfig = new ComponentName("device", "config");
+        setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
+        when(mResources
+                .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
+                .thenReturn(xmlConfig.flattenToString());
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
+                .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
+        mService.setNotificationAssistantAccessGrantedCallback(
+                mNotificationAssistantAccessGrantedCallback);
+
+        mService.setDefaultAssistantForUser(0);
+
+        verify(mNotificationAssistantAccessGrantedCallback)
+                .onGranted(eq(deviceConfig), eq(0), eq(true));
+    }
+
+    @Test
+    public void setDefaultAssistantForUser_deviceConfigInvalid() {
+        ComponentName xmlConfig = new ComponentName("xml", "config");
+        ComponentName deviceConfig = new ComponentName("device", "config");
+        setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
+        when(mResources
+                .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
+                .thenReturn(xmlConfig.flattenToString());
+        when(mContext.getResources()).thenReturn(mResources);
+        // Only xmlConfig is valid, deviceConfig is not.
+        when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
+                .thenReturn(Collections.singleton(xmlConfig));
+        mService.setNotificationAssistantAccessGrantedCallback(
+                mNotificationAssistantAccessGrantedCallback);
+
+        mService.setDefaultAssistantForUser(0);
+
+        verify(mNotificationAssistantAccessGrantedCallback)
+                .onGranted(eq(xmlConfig), eq(0), eq(true));
+    }
+
+    private void clearDeviceConfig() {
+        DeviceConfig.resetToDefaults(
+                Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
+    }
+
+    private void setDefaultAssistantInDeviceConfig(String componentName) {
+        DeviceConfig.setProperty(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
+                componentName,
+                false);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 56f4a85..85e8a14 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -40,13 +40,19 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 
+import android.app.TaskStackListener;
+import android.content.pm.ActivityInfo;
+import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
-import org.junit.Before;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Tests for the {@link ActivityDisplay} class.
  *
@@ -331,4 +337,45 @@
         verify(mSupervisor).removeTaskByIdLocked(eq(task1.taskId), anyBoolean(), anyBoolean(),
                 any());
     }
+
+    /**
+     * Ensures that {@link TaskStackListener} can receive callback about the activity in size
+     * compatibility mode.
+     */
+    @Test
+    public void testHandleActivitySizeCompatMode() throws Exception {
+        final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+        final ActivityRecord activity = createFullscreenStackWithSimpleActivityAt(
+                display).topRunningActivityLocked();
+        activity.setState(ActivityStack.ActivityState.RESUMED, "testHandleActivitySizeCompatMode");
+        activity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        activity.info.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+        activity.getTaskRecord().getConfiguration().windowConfiguration.getBounds().set(
+                0, 0, 1000, 2000);
+
+        final ArrayList<CompletableFuture<IBinder>> resultWrapper = new ArrayList<>();
+        mService.getTaskChangeNotificationController().registerTaskStackListener(
+                new TaskStackListener() {
+                    @Override
+                    public void onSizeCompatModeActivityChanged(int displayId,
+                            IBinder activityToken) {
+                        resultWrapper.get(0).complete(activityToken);
+                    }
+                });
+
+        // Expect the exact component name when the activity is in size compatible mode.
+        activity.getResolvedOverrideConfiguration().windowConfiguration.getBounds().set(
+                0, 0, 800, 1600);
+        resultWrapper.add(new CompletableFuture<>());
+        display.handleActivitySizeCompatModeIfNeeded(activity);
+
+        assertEquals(activity.appToken, resultWrapper.get(0).get(2, TimeUnit.SECONDS));
+
+        // Expect null component name when switching to non-size-compat mode activity.
+        activity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
+        resultWrapper.set(0, new CompletableFuture<>());
+        display.handleActivitySizeCompatModeIfNeeded(activity);
+
+        assertNull(resultWrapper.get(0).get(2, TimeUnit.SECONDS));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 1319bad..457d9c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -21,6 +21,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -38,6 +39,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -171,6 +173,24 @@
     }
 
     @Test
+    public void testRestartProcessIfVisible() {
+        doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity);
+        mActivity.getParent().getWindowConfiguration().setAppBounds(0, 0, 500, 1000);
+        mActivity.visible = true;
+        mActivity.haveState = false;
+        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+        mActivity.info.maxAspectRatio = 1.5f;
+        mActivity.setState(ActivityStack.ActivityState.RESUMED, "testRestart");
+        final Rect originalOverrideBounds = new Rect(0, 0, 400, 600);
+        mActivity.setBounds(originalOverrideBounds);
+
+        mService.restartActivityProcessIfVisible(mActivity.appToken);
+
+        assertEquals(ActivityStack.ActivityState.RESTARTING_PROCESS, mActivity.getState());
+        assertNotEquals(originalOverrideBounds, mActivity.getBounds());
+    }
+
+    @Test
     public void testsApplyOptionsLocked() {
         ActivityOptions activityOptions = ActivityOptions.makeBasic();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 606ab31..d02db7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -561,7 +561,7 @@
         runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
     }
 
     /**
@@ -576,7 +576,7 @@
                 "disallowed_unsupportedUsecase_aborted", true,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
     }
 
     /**
@@ -591,61 +591,66 @@
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted", false,
                 Process.ROOT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted", false,
                 Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest("disallowed_nfcUid_notAborted", false,
                 Process.NFC_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidHasVisibleWindow_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, true, PROCESS_STATE_TOP + 1,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_realCallingUidProcessStateTop_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
-                false, false, false, false, false);
+                false, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_hasForegroundActivities_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                true, false, false, false, false);
+                true, false, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsRecents_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, true, false, false, false);
+                false, true, false, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsWhitelisted_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, true, false, false);
+                false, false, true, false, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callerIsInstrumentingWithBackgroundActivityStartPrivileges_notAborted",
                 false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, true, false);
+                false, false, false, true, false, false);
         runAndVerifyBackgroundActivityStartsSubtest(
                 "disallowed_callingPackageNameIsDeviceOwner_notAborted", false,
                 UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
                 UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
-                false, false, false, false, true);
+                false, false, false, false, true, false);
+        runAndVerifyBackgroundActivityStartsSubtest(
+                "disallowed_callingPackageNameIsTempWhitelisted_notAborted", false,
+                UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+                UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+                false, false, false, false, false, true);
     }
 
     private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
@@ -654,7 +659,7 @@
             boolean hasForegroundActivities, boolean callerIsRecents,
             boolean callerIsTempWhitelisted,
             boolean callerIsInstrumentingWithBackgroundActivityStartPrivileges,
-            boolean isCallingPackageNameDeviceOwner) {
+            boolean isCallingPackageNameDeviceOwner, boolean isCallingPackageTempWhitelisted) {
         // window visibility
         doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                 .isAnyNonToastWindowVisibleForUid(callingUid);
@@ -680,11 +685,15 @@
         // caller is instrumenting with background activity starts privileges
         callerApp.setInstrumenting(callerIsInstrumentingWithBackgroundActivityStartPrivileges,
                 callerIsInstrumentingWithBackgroundActivityStartPrivileges);
-        // calling package name is whitelisted
+        // calling package name is the device owner
         doReturn(isCallingPackageNameDeviceOwner).when(mService).isDeviceOwner(any());
+        // calling package name is temporarily whitelisted
+        doReturn(isCallingPackageTempWhitelisted).when(mService)
+                .isPackageNameWhitelistedForBgActivityStarts("com.whatever.dude");
 
         final ActivityOptions options = spy(ActivityOptions.makeBasic());
         ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
+                .setCallingPackage("com.whatever.dude")
                 .setCaller(caller)
                 .setCallingUid(callingUid)
                 .setRealCallingUid(realCallingUid)
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index b91f3ec..6e09167 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -23,29 +23,29 @@
 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
 
-import androidx.test.filters.SmallTest;
-
 import org.junit.Before;
 import org.junit.Test;
 
+import androidx.test.filters.SmallTest;
+
 /**
  * Test class for {@link AppTransition}.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:AppTransitionTests
+ *  atest WmTests:AppTransitionTests
  */
 @SmallTest
 @Presubmit
@@ -167,4 +167,11 @@
         assertFalse(dc1.mOpeningApps.contains(token1));
     }
 
+    @Test
+    public void testLoadAnimationSafely() {
+        DisplayContent dc = createNewDisplay(Display.STATE_ON);
+        assertNull(dc.mAppTransition.loadAnimationSafely(
+                getInstrumentation().getTargetContext(), -1));
+    }
+
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 763ea62..a03d28b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -40,7 +40,6 @@
 import android.view.IRecentsAnimationRunner;
 import android.view.SurfaceControl;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
@@ -113,7 +112,6 @@
     }
 
     @Test
-    @FlakyTest(bugId = 117117823)
     public void testIncludedApps_expectTargetAndVisible() {
         mWm.setRecentsAnimationController(mController);
         final AppWindowToken homeAppWindow = createAppWindowToken(mDisplayContent,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 5d07888..dc307b5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -47,6 +47,7 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.service.voice.IVoiceInteractionSession;
+import android.util.DisplayMetrics;
 import android.util.Xml;
 import android.view.DisplayInfo;
 
@@ -166,6 +167,44 @@
                 WINDOWING_MODE_FREEFORM, mParentBounds, insetBounds, insetBounds);
     }
 
+    @Test
+    public void testFitWithinBounds() {
+        final Rect parentBounds = new Rect(10, 10, 200, 200);
+        ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
+        ActivityStack stack = display.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD,
+                true /* onTop */);
+        TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+        final Configuration parentConfig = stack.getConfiguration();
+        parentConfig.windowConfiguration.setBounds(parentBounds);
+        parentConfig.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+
+        // check top and left
+        Rect reqBounds = new Rect(-190, -190, 0, 0);
+        task.setBounds(reqBounds);
+        // Make sure part of it is exposed
+        assertTrue(task.getBounds().right > parentBounds.left);
+        assertTrue(task.getBounds().bottom > parentBounds.top);
+        // Should still be more-or-less in that corner
+        assertTrue(task.getBounds().left <= parentBounds.left);
+        assertTrue(task.getBounds().top <= parentBounds.top);
+
+        assertEquals(reqBounds.width(), task.getBounds().width());
+        assertEquals(reqBounds.height(), task.getBounds().height());
+
+        // check bottom and right
+        reqBounds = new Rect(210, 210, 400, 400);
+        task.setBounds(reqBounds);
+        // Make sure part of it is exposed
+        assertTrue(task.getBounds().left < parentBounds.right);
+        assertTrue(task.getBounds().top < parentBounds.bottom);
+        // Should still be more-or-less in that corner
+        assertTrue(task.getBounds().right >= parentBounds.right);
+        assertTrue(task.getBounds().bottom >= parentBounds.bottom);
+
+        assertEquals(reqBounds.width(), task.getBounds().width());
+        assertEquals(reqBounds.height(), task.getBounds().height());
+    }
+
     /** Tests that the task bounds adjust properly to changes between FULLSCREEN and FREEFORM */
     @Test
     public void testBoundsOnModeChangeFreeformToFullscreen() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 42a205a..b140da5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -100,7 +100,6 @@
     }
 
     @Test
-    @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
     public void testTaskDescriptionChanged() throws Exception {
         final Object[] params = new Object[2];
         final CountDownLatch latch = new CountDownLatch(1);
@@ -133,7 +132,6 @@
     }
 
     @Test
-    @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
     public void testActivityRequestedOrientationChanged() throws Exception {
         final int[] params = new int[2];
         final CountDownLatch latch = new CountDownLatch(1);
@@ -214,6 +212,7 @@
 
         // Test for onTaskRemovalStarted.
         assertEquals(1, taskRemovalStartedLatch.getCount());
+        assertEquals(1, taskRemovedLatch.getCount());
         activity.finishAndRemoveTask();
         waitForCallback(taskRemovalStartedLatch);
         // onTaskRemovalStarted happens before the activity's window is removed.
@@ -221,7 +220,6 @@
         assertEquals(id, params[0]);
 
         // Test for onTaskRemoved.
-        assertEquals(1, taskRemovedLatch.getCount());
         waitForCallback(taskRemovedLatch);
         assertEquals(id, params[0]);
         waitForCallback(onDetachedFromWindowLatch);
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index bc54a5d..1e4861a 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -508,6 +508,16 @@
                 Integer.toString(userId)), APP_IDLE_FILENAME);
     }
 
+
+    /**
+     * Check if App Idle File exists on disk
+     * @param userId
+     * @return true if file exists
+     */
+    public boolean userFileExists(int userId) {
+        return getUserFile(userId).exists();
+    }
+
     private void readAppIdleTimes(int userId, ArrayMap<String, AppUsageHistory> userHistory) {
         FileInputStream fis = null;
         try {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index ffafb6d..4b33e16 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -377,7 +377,12 @@
 
             mSystemServicesReady = true;
 
-            if (mPendingInitializeDefaults) {
+            boolean userFileExists;
+            synchronized (mAppIdleLock) {
+                userFileExists = mAppIdleHistory.userFileExists(UserHandle.USER_SYSTEM);
+            }
+
+            if (mPendingInitializeDefaults || !userFileExists) {
                 initializeDefaultsForSystemApps(UserHandle.USER_SYSTEM);
             }
 
@@ -1435,6 +1440,8 @@
                             elapsedRealtime + mSystemUpdateUsageTimeoutMillis);
                 }
             }
+            // Immediately persist defaults to disk
+            mAppIdleHistory.writeAppIdleTimes(userId);
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index 731cbf4..f3d6387 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -511,8 +511,10 @@
 
     class AppUsageLimitGroup extends UsageGroup {
         public AppUsageLimitGroup(UserData user, ObserverAppData observerApp, int observerId,
-                String[] observed, long timeLimitMs, PendingIntent limitReachedCallback) {
+                String[] observed, long timeLimitMs, long timeRemainingMs,
+                PendingIntent limitReachedCallback) {
             super(user, observerApp, observerId, observed, timeLimitMs, limitReachedCallback);
+            mUsageTimeMs = timeLimitMs - timeRemainingMs;
         }
 
         @Override
@@ -839,9 +841,9 @@
      * Existing app usage limit observer with the same observerId will be removed.
      */
     public void addAppUsageLimitObserver(int requestingUid, int observerId, String[] observed,
-            long timeLimit, PendingIntent callbackIntent, @UserIdInt int userId) {
-        // Allow the special case of the limit being 0, but with no callback.
-        if (timeLimit != 0L && timeLimit < getMinTimeLimit()) {
+            long timeLimit, long timeRemaining, PendingIntent callbackIntent,
+            @UserIdInt int userId) {
+        if (timeLimit < getMinTimeLimit()) {
             throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit());
         }
         synchronized (mLock) {
@@ -859,7 +861,7 @@
                         "Too many app usage observers added by uid " + requestingUid);
             }
             group = new AppUsageLimitGroup(user, observerApp, observerId, observed, timeLimit,
-                    timeLimit == 0L ? null : callbackIntent);
+                    timeRemaining, timeRemaining == 0L ? null : callbackIntent);
             observerApp.appUsageLimitGroups.append(observerId, group);
 
             if (DEBUG) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index b14d722..27fdbcb 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1399,7 +1399,8 @@
 
         @Override
         public void registerAppUsageLimitObserver(int observerId, String[] packages,
-                long timeLimitMs, PendingIntent callbackIntent, String callingPackage) {
+                long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent,
+                String callingPackage) {
             if (!hasPermissions(callingPackage,
                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
                 throw new SecurityException("Caller doesn't have both SUSPEND_APPS and "
@@ -1409,7 +1410,11 @@
             if (packages == null || packages.length == 0) {
                 throw new IllegalArgumentException("Must specify at least one package");
             }
-            if (callbackIntent == null && timeLimitMs != 0L) {
+            if (timeRemainingMs > timeLimitMs) {
+                throw new IllegalArgumentException(
+                        "Remaining time can't be greater than total time.");
+            }
+            if (callbackIntent == null && timeRemainingMs != 0L) {
                 throw new NullPointerException("callbackIntent can't be null");
             }
             final int callingUid = Binder.getCallingUid();
@@ -1417,7 +1422,7 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId,
-                        packages, timeLimitMs, callbackIntent, userId);
+                        packages, timeLimitMs, timeRemainingMs, callbackIntent, userId);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1545,9 +1550,9 @@
     }
 
     void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages,
-            long timeLimitMs, PendingIntent callbackIntent, int userId) {
-        mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages, timeLimitMs,
-                callbackIntent, userId);
+            long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent, int userId) {
+        mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages,
+                timeLimitMs, timeRemainingMs, callbackIntent, userId);
     }
 
     void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 57729b5..1bf0723 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -16,9 +16,6 @@
 
 package com.android.server.voiceinteraction;
 
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
-import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
 import static android.app.AppOpsManager.OP_ASSIST_SCREENSHOT;
 import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
 import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
@@ -26,6 +23,10 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
+import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.AppOpsManager;
@@ -256,7 +257,10 @@
             final Bundle assistData = data.getBundle(ASSIST_KEY_DATA);
             final AssistStructure structure = data.getParcelable(ASSIST_KEY_STRUCTURE);
             final AssistContent content = data.getParcelable(ASSIST_KEY_CONTENT);
-            final int uid = data.getInt(Intent.EXTRA_ASSIST_UID, -1);
+            int uid = -1;
+            if (assistData != null) {
+                uid = assistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
+            }
             if (uid >= 0 && content != null) {
                 Intent intent = content.getIntent();
                 if (intent != null) {
diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp
index 5ac4a46..4359978 100644
--- a/startop/iorap/tests/Android.bp
+++ b/startop/iorap/tests/Android.bp
@@ -29,7 +29,7 @@
 
       // test android dependencies
       "platform-test-annotations",
-      "android-support-test",
+      "androidx.test.rules",
       // test framework dependencies
       "mockito-target-inline-minus-junit4",
       // "mockito-target-minus-junit4",
diff --git a/startop/iorap/tests/AndroidManifest.xml b/startop/iorap/tests/AndroidManifest.xml
index 99f4add..b967e72 100644
--- a/startop/iorap/tests/AndroidManifest.xml
+++ b/startop/iorap/tests/AndroidManifest.xml
@@ -22,7 +22,7 @@
 
     <!--suppress AndroidDomInspection -->
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.google.android.startop.iorap.tests" />
 
       <!--
diff --git a/startop/iorap/tests/AndroidTest.xml b/startop/iorap/tests/AndroidTest.xml
index 919154d..bcd1103 100644
--- a/startop/iorap/tests/AndroidTest.xml
+++ b/startop/iorap/tests/AndroidTest.xml
@@ -44,7 +44,7 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.google.android.startop.iorap.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
 
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
index 16dcbe2..b1e6194 100644
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
@@ -14,12 +14,14 @@
 
 package com.google.android.startop.iorap
 
-import android.net.Uri
 import android.os.ServiceManager
-import android.support.test.filters.MediumTest
+import androidx.test.filters.MediumTest
 import org.junit.Test
-import org.junit.Ignore
-import org.mockito.Mockito.*
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.timeout
 
 // @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
 @MediumTest
@@ -27,7 +29,7 @@
     /**
      * @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
      */
-    private val iorapService : IIorap by lazy {
+    private val iorapService: IIorap by lazy {
         // TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
         IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
 
@@ -39,7 +41,7 @@
 
     // A dummy binder stub implementation is required to use with mockito#spy.
     // Mockito overrides the methods at runtime and tracks how methods were invoked.
-    open class DummyTaskListener : ITaskListener.Stub()  {
+    open class DummyTaskListener : ITaskListener.Stub() {
         // Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
         // from using the mockito matchers (eq, argThat, etc).
         override fun onProgress(requestId: RequestId?, result: TaskResult?) {
@@ -49,7 +51,7 @@
         }
     }
 
-    private fun testAnyMethod(func : (RequestId) -> Unit) {
+    private fun testAnyMethod(func: (RequestId) -> Unit) {
         val taskListener = spy(DummyTaskListener())!!
 
         try {
@@ -68,14 +70,13 @@
 
             // The "stub" behavior of iorapd is that every request immediately gets a response of
             //   BEGAN,ONGOING,COMPLETED
-            inOrder.verify(taskListener, timeout(100)).
-                  onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
-            inOrder.verify(taskListener, timeout(100)).
-                  onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
-            inOrder.verify(taskListener, timeout(100)).
-                  onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
+            inOrder.verify(taskListener, timeout(100))
+                .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
+            inOrder.verify(taskListener, timeout(100))
+                .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
+            inOrder.verify(taskListener, timeout(100))
+                .onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
             inOrder.verifyNoMoreInteractions()
-
         } finally {
             // iorapService.setTaskListener(null)
             // FIXME: null is broken, C++ side sees a non-null object.
@@ -96,7 +97,7 @@
 
     @Test
     fun testOnAppIntentEvent() {
-        testAnyMethod { requestId : RequestId ->
+        testAnyMethod { requestId: RequestId ->
             iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
                     ActivityInfo("dont care", "dont care"),
                     ActivityInfo("dont care 2", "dont care 2")))
@@ -105,7 +106,7 @@
 
     @Test
     fun testOnSystemServiceEvent() {
-        testAnyMethod { requestId : RequestId ->
+        testAnyMethod { requestId: RequestId ->
             iorapService.onSystemServiceEvent(requestId,
                     SystemServiceEvent(SystemServiceEvent.TYPE_START))
         }
@@ -113,9 +114,9 @@
 
     @Test
     fun testOnSystemServiceUserEvent() {
-        testAnyMethod { requestId : RequestId ->
+        testAnyMethod { requestId: RequestId ->
             iorapService.onSystemServiceUserEvent(requestId,
-                    SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER,0))
+                    SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 0))
         }
     }
 }
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
index 4abbb3e..8fa0cde 100644
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
@@ -17,7 +17,7 @@
 import android.net.Uri
 import android.os.Parcel
 import android.os.Parcelable
-import android.support.test.filters.SmallTest
+import androidx.test.filters.SmallTest
 import org.junit.Test
 import org.junit.runner.RunWith
 import com.google.common.truth.Truth.assertThat
@@ -29,7 +29,7 @@
  */
 @SmallTest
 @RunWith(Parameterized::class)
-class ParcelablesTest<T : Parcelable>(private val inputData : InputData<T>) {
+class ParcelablesTest<T : Parcelable>(private val inputData: InputData<T>) {
     companion object {
         private val initialRequestId = RequestId.nextValueForSequence()!!
 
@@ -73,19 +73,19 @@
                         TaskResult(TaskResult.STATE_ONGOING))
         )
 
-        private fun newActivityInfo() : ActivityInfo {
+        private fun newActivityInfo(): ActivityInfo {
             return ActivityInfo("some package", "some activity")
         }
 
-        private fun newActivityInfoOther() : ActivityInfo {
+        private fun newActivityInfoOther(): ActivityInfo {
             return ActivityInfo("some package 2", "some activity 2")
         }
 
-        private fun newUri() : Uri {
+        private fun newUri(): Uri {
             return Uri.parse("https://www.google.com")
         }
 
-        private fun cloneRequestId(requestId: RequestId) : RequestId {
+        private fun cloneRequestId(requestId: RequestId): RequestId {
             val constructor = requestId::class.java.declaredConstructors[0]
             constructor.isAccessible = true
             return constructor.newInstance(requestId.requestId) as RequestId
@@ -108,7 +108,7 @@
     @Test
     fun testParcelRoundTrip() {
         // calling writeToParcel and then T::CREATOR.createFromParcel would return the same data.
-        val assertParcels = { it : T, data : InputData<T> ->
+        val assertParcels = { it: T, data: InputData<T> ->
             val parcel = Parcel.obtain()
             it.writeToParcel(parcel, 0)
             parcel.setDataPosition(0) // future reads will see all previous writes.
@@ -121,7 +121,7 @@
         assertParcels(inputData.validOther, inputData)
     }
 
-    data class InputData<T : Parcelable>(val valid : T, val validCopy : T, val validOther : T) {
+    data class InputData<T : Parcelable>(val valid: T, val validCopy: T, val validOther: T) {
         val kls = valid.javaClass
         init {
             assertThat(valid).isNotSameAs(validCopy)
@@ -130,8 +130,8 @@
             assertThat(validOther.javaClass).isEqualTo(valid.javaClass)
         }
 
-        fun createFromParcel(parcel : Parcel) : T {
-            val field  = kls.getDeclaredField("CREATOR")
+        fun createFromParcel(parcel: Parcel): T {
+            val field = kls.getDeclaredField("CREATOR")
             val creator = field.get(null) as Parcelable.Creator<T>
 
             return creator.createFromParcel(parcel)
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
index ac60e96..22a3cfa 100644
--- a/startop/view_compiler/dex_builder_test/Android.bp
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -43,7 +43,7 @@
     sdk_version: "current",
     data: [":generate_dex_testcases", ":generate_compiled_layout1", ":generate_compiled_layout2"],
     static_libs: [
-        "android-support-test",
+        "androidx.test.rules",
         "guava",
     ],
     manifest: "AndroidManifest.xml",
diff --git a/startop/view_compiler/dex_builder_test/AndroidManifest.xml b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
index 6ac5fc5..b335663 100644
--- a/startop/view_compiler/dex_builder_test/AndroidManifest.xml
+++ b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
@@ -22,7 +22,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.startop.test"
                      android:label="DexBuilder Tests"/>
 
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
index 92e2a71..82509b9 100644
--- a/startop/view_compiler/dex_builder_test/AndroidTest.xml
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -31,6 +31,6 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.startop.test" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 42d4161..f7b1674 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -14,18 +14,14 @@
 
 package android.startop.test;
 
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import com.google.common.io.ByteStreams;
-import dalvik.system.InMemoryDexClassLoader;
 import dalvik.system.PathClassLoader;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
+
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
 // Adding tests here requires changes in several other places. See README.md in
 // the view_compiler directory for more information.
 public class DexBuilderTest {
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
index a3b1b6c..3dfb20c 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java
@@ -15,18 +15,15 @@
 package android.startop.test;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.view.View;
-import com.google.common.io.ByteStreams;
-import dalvik.system.InMemoryDexClassLoader;
+
+import androidx.test.InstrumentationRegistry;
+
 import dalvik.system.PathClassLoader;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-import org.junit.Assert;
+
 import org.junit.Test;
 
+import java.lang.reflect.Method;
+
 // Adding tests here requires changes in several other places. See README.md in
 // the view_compiler directory for more information.
 public class LayoutCompilerTest {
diff --git a/telecomm/java/android/telecom/CallIdentification.java b/telecomm/java/android/telecom/CallIdentification.java
index d15e024..745affd 100644
--- a/telecomm/java/android/telecom/CallIdentification.java
+++ b/telecomm/java/android/telecom/CallIdentification.java
@@ -44,7 +44,7 @@
      * A {@link CallScreeningService} uses this class to create new instances of
      * {@link CallIdentification} for a screened call.
      */
-    public static class Builder {
+    public final static class Builder {
         private CharSequence mName;
         private CharSequence mDescription;
         private CharSequence mDetails;
@@ -67,7 +67,7 @@
          * @param callIdAppName The app name.
          * @hide
          */
-        public Builder(String callIdPackageName, CharSequence callIdAppName) {
+        public Builder(@NonNull String callIdPackageName, @NonNull CharSequence callIdAppName) {
             mPackageName = callIdPackageName;
             mAppName = callIdAppName;
         }
@@ -80,7 +80,7 @@
          * @param name The name associated with the call, or {@code null} if none is provided.
          * @return Builder instance.
          */
-        public Builder setName(@Nullable CharSequence name) {
+        public @NonNull Builder setName(@Nullable CharSequence name) {
             mName = name;
             return this;
         }
@@ -97,7 +97,7 @@
          * @param description The call description, or {@code null} if none is provided.
          * @return Builder instance.
          */
-        public Builder setDescription(@Nullable CharSequence description) {
+        public @NonNull Builder setDescription(@Nullable CharSequence description) {
             mDescription = description;
             return this;
         }
@@ -114,7 +114,8 @@
          * @param details The call details, or {@code null} if none is provided.
          * @return Builder instance.
          */
-        public Builder setDetails(@Nullable CharSequence details) {
+
+        public @NonNull Builder setDetails(@Nullable CharSequence details) {
             mDetails = details;
             return this;
         }
@@ -127,7 +128,7 @@
          * @param photo The photo associated with the call, or {@code null} if none was provided.
          * @return Builder instance.
          */
-        public Builder setPhoto(@Nullable Icon photo) {
+        public @NonNull Builder setPhoto(@Nullable Icon photo) {
             mPhoto = photo;
             return this;
         }
@@ -141,7 +142,7 @@
          * @param nuisanceConfidence The nuisance confidence.
          * @return The builder.
          */
-        public Builder setNuisanceConfidence(@NuisanceConfidence int nuisanceConfidence) {
+        public @NonNull Builder setNuisanceConfidence(@NuisanceConfidence int nuisanceConfidence) {
             mNuisanceConfidence = nuisanceConfidence;
             return this;
         }
@@ -152,7 +153,7 @@
          *
          * @return {@link CallIdentification} instance.
          */
-        public CallIdentification build() {
+        public @NonNull CallIdentification build() {
             return new CallIdentification(mName, mDescription, mDetails, mPhoto,
                     mNuisanceConfidence, mPackageName, mAppName);
         }
diff --git a/telecomm/java/android/telecom/PhoneAccountSuggestion.java b/telecomm/java/android/telecom/PhoneAccountSuggestion.java
index 3799cf3..2589d95 100644
--- a/telecomm/java/android/telecom/PhoneAccountSuggestion.java
+++ b/telecomm/java/android/telecom/PhoneAccountSuggestion.java
@@ -18,8 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -69,10 +67,15 @@
     private boolean mShouldAutoSelect;
 
     /**
-     * @hide
+     * Creates a new instance of {@link PhoneAccountSuggestion}. This constructor is intended for
+     * use by apps implementing a {@link PhoneAccountSuggestionService}, and generally should not be
+     * used by dialer apps other than for testing purposes.
+     *
+     * @param handle The {@link PhoneAccountHandle} for this suggestion.
+     * @param reason The reason for this suggestion
+     * @param shouldAutoSelect Whether the dialer should automatically place the call using this
+     *                         account. See {@link #shouldAutoSelect()}.
      */
-    @SystemApi
-    @TestApi
     public PhoneAccountSuggestion(@NonNull PhoneAccountHandle handle, @SuggestionReason int reason,
             boolean shouldAutoSelect) {
         this.mHandle = handle;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index d509168..7688ac6 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -17,6 +17,7 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SuppressLint;
@@ -814,10 +815,11 @@
      * <p>
      * The default dialer has access to use this method.
      *
-     * @return The user outgoing phone account selected by the user.
+     * @return The user outgoing phone account selected by the user, or {@code null} if there is no
+     * user selected outgoing {@link PhoneAccountHandle}.
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
+    public @Nullable PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().getUserSelectedOutgoingPhoneAccount(
@@ -833,13 +835,14 @@
      * Sets the user-chosen default {@link PhoneAccountHandle} for making outgoing phone calls.
      *
      * @param accountHandle The {@link PhoneAccountHandle} which will be used by default for making
-     *                      outgoing voice calls.
+     *                      outgoing voice calls, or {@code null} if no default is specified (the
+     *                      user will be asked each time a call is placed in this case).
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     @TestApi
     @SystemApi
-    public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
+    public void setUserSelectedOutgoingPhoneAccount(@Nullable PhoneAccountHandle accountHandle) {
         try {
             if (isServiceConnected()) {
                 getTelecomService().setUserSelectedOutgoingPhoneAccount(accountHandle);
@@ -1206,7 +1209,8 @@
     /**
      * Used to set the default dialer package.
      *
-     * @param packageName to set the default dialer to.
+     * @param packageName to set the default dialer to, or {@code null} if the system provided
+     *                    dialer should be used instead.
      *
      * @result {@code true} if the default dialer was successfully changed, {@code false} if
      *         the specified package does not correspond to an installed dialer, or is already
@@ -1225,7 +1229,7 @@
     @RequiresPermission(allOf = {
             android.Manifest.permission.MODIFY_PHONE_STATE,
             android.Manifest.permission.WRITE_SECURE_SETTINGS})
-    public boolean setDefaultDialer(String packageName) {
+    public boolean setDefaultDialer(@Nullable String packageName) {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().setDefaultDialer(packageName);
@@ -1239,9 +1243,10 @@
     /**
      * Determines the package name of the system-provided default phone app.
      *
-     * @return package name for the system dialer package or null if no system dialer is preloaded.
+     * @return package name for the system dialer package or {@code null} if no system dialer is
+     *         preloaded.
      */
-    public String getSystemDialerPackage() {
+    public @Nullable String getSystemDialerPackage() {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().getSystemDialerPackage();
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 79b7807..67477cf 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -1191,8 +1191,8 @@
              * Broadcast Action: A debug code has been entered in the dialer. This intent is
              * broadcast by the system and OEM telephony apps may need to receive these broadcasts.
              * These "secret codes" are used to activate developer menus by dialing certain codes.
-             * And they are of the form {@code *#*#&lt;code&gt;#*#*}. The intent will have the data
-             * URI: {@code android_secret_code://&lt;code&gt;}. It is possible that a manifest
+             * And they are of the form {@code *#*#<code>#*#*}. The intent will have the data
+             * URI: {@code android_secret_code://<code>}. It is possible that a manifest
              * receiver would be woken up even if it is not currently running.
              *
              * <p>Requires {@code android.Manifest.permission#CONTROL_INCALL_EXPERIENCE} to
@@ -3829,6 +3829,42 @@
          */
         public static final String CARRIER_ID = "carrier_id";
 
+        /**
+         * The skip 464xlat flag. Flag works as follows.
+         * {@link #SKIP_464XLAT_DEFAULT}: the APN will skip only APN is IMS and no internet.
+         * {@link #SKIP_464XLAT_DISABLE}: the APN will NOT skip 464xlat
+         * {@link #SKIP_464XLAT_ENABLE}: the APN will skip 464xlat
+         * <p>Type: INTEGER</p>
+         *
+         * @hide
+         */
+        public static final String SKIP_464XLAT = "skip_464xlat";
+
+        /**
+         * Possible value for the {@link #SKIP_464XLAT} field.
+         * <p>Type: INTEGER</p>
+         *
+         * @hide
+         */
+        public static final int SKIP_464XLAT_DEFAULT = -1;
+
+        /**
+         * Possible value for the {@link #SKIP_464XLAT} field.
+         * <p>Type: INTEGER</p>
+         *
+         * @hide
+         */
+        public static final int SKIP_464XLAT_DISABLE = 0;
+
+        /**
+         * Possible value for the {@link #SKIP_464XLAT} field.
+         * <p>Type: INTEGER</p>
+         *
+         * @hide
+         */
+        public static final int SKIP_464XLAT_ENABLE = 1;
+
+
         /** @hide */
         @IntDef({
                 UNEDITED,
@@ -3839,6 +3875,16 @@
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface EditStatus {}
+
+        /** @hide */
+        @IntDef({
+                SKIP_464XLAT_DEFAULT,
+                SKIP_464XLAT_DISABLE,
+                SKIP_464XLAT_ENABLE,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Skip464XlatStatus {}
+
     }
 
     /**
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index 368f0c6..3a34005 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -29,15 +30,15 @@
  * @hide
  */
 @SystemApi
-public class CallAttributes implements Parcelable {
+public final class CallAttributes implements Parcelable {
     private PreciseCallState mPreciseCallState;
     @NetworkType
     private int mNetworkType; // TelephonyManager.NETWORK_TYPE_* ints
     private CallQuality mCallQuality;
 
 
-    public CallAttributes(PreciseCallState state, @NetworkType int networkType,
-            CallQuality callQuality) {
+    public CallAttributes(@NonNull PreciseCallState state, @NetworkType int networkType,
+            @NonNull CallQuality callQuality) {
         this.mPreciseCallState = state;
         this.mNetworkType = networkType;
         this.mCallQuality = callQuality;
@@ -59,6 +60,7 @@
     /**
      * Returns the {@link PreciseCallState} of the call.
      */
+    @NonNull
     public PreciseCallState getPreciseCallState() {
         return mPreciseCallState;
     }
@@ -96,6 +98,7 @@
     /**
      * Returns the {#link CallQuality} of the call.
      */
+    @NonNull
     public CallQuality getCallQuality() {
         return mCallQuality;
     }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c0444bb..d680b89 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1812,17 +1812,32 @@
 
     /**
      * Determine whether user can change Wi-Fi Calling preference in roaming.
-     * {@code false} - roaming preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT} is
-     *                 the same as home preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT}
-     *                 and cannot be changed.
-     * {@code true}  - roaming preference can be changed by user independently.
-     *
+     * {@code false} - roaming preference cannot be changed by user independently. If
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false,
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT} is used as the default
+     *                 value. If {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is
+     *                 true, roaming preference is the same as home preference and
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
+     * {@code true}  - roaming preference can be changed by user independently if
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false. If
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is true, this
+     *                 configuration is ignored and roaming preference cannot be changed.
      * @hide
      */
     public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL =
             "editable_wfc_roaming_mode_bool";
 
     /**
+     * Flag specifying whether the carrier will use the WFC home network mode in roaming network.
+     * {@code false} - roaming preference can be selected separately from the home preference.
+     * {@code true}  - roaming preference is the same as home preference and
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
+     * @hide
+     */
+    public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL =
+            "use_wfc_home_network_mode_in_roaming_network_bool";
+
+    /**
      * Carrier specified WiFi networks.
      * @hide
      */
@@ -2911,6 +2926,7 @@
         sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
         sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+        sDefaults.putBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
         sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
         sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
         sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java
index 47ce632..78623e7 100644
--- a/telephony/java/android/telephony/CarrierRestrictionRules.java
+++ b/telephony/java/android/telephony/CarrierRestrictionRules.java
@@ -177,7 +177,8 @@
      * @return a list of boolean with the same size as input, indicating if each
      * {@link CarrierIdentifier} is allowed or not.
      */
-    public List<Boolean> isCarrierIdentifiersAllowed(@NonNull List<CarrierIdentifier> carrierIds) {
+    public @NonNull List<Boolean> areCarrierIdentifiersAllowed(
+            @NonNull List<CarrierIdentifier> carrierIds) {
         ArrayList<Boolean> result = new ArrayList<>(carrierIds.size());
 
         // First calculate the result for each slot independently
@@ -332,7 +333,7 @@
     /**
      * Builder for a {@link CarrierRestrictionRules}.
      */
-    public static class Builder {
+    public static final class Builder {
         private final CarrierRestrictionRules mRules;
 
         /** {@hide} */
@@ -341,14 +342,14 @@
         }
 
         /** build command */
-        public CarrierRestrictionRules build() {
+        public @NonNull CarrierRestrictionRules build() {
             return mRules;
         }
 
         /**
          * Indicate that all carriers are allowed.
          */
-        public Builder setAllCarriersAllowed() {
+        public @NonNull Builder setAllCarriersAllowed() {
             mRules.mAllowedCarriers.clear();
             mRules.mExcludedCarriers.clear();
             mRules.mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_ALLOWED;
@@ -360,7 +361,8 @@
          *
          * @param allowedCarriers list of allowed carriers
          */
-        public Builder setAllowedCarriers(List<CarrierIdentifier> allowedCarriers) {
+        public @NonNull Builder setAllowedCarriers(
+                @NonNull List<CarrierIdentifier> allowedCarriers) {
             mRules.mAllowedCarriers = new ArrayList<CarrierIdentifier>(allowedCarriers);
             return this;
         }
@@ -370,7 +372,8 @@
          *
          * @param excludedCarriers list of excluded carriers
          */
-        public Builder setExcludedCarriers(List<CarrierIdentifier> excludedCarriers) {
+        public @NonNull Builder setExcludedCarriers(
+                @NonNull List<CarrierIdentifier> excludedCarriers) {
             mRules.mExcludedCarriers = new ArrayList<CarrierIdentifier>(excludedCarriers);
             return this;
         }
@@ -380,7 +383,7 @@
          *
          * @param carrierRestrictionDefault prioritized carrier list
          */
-        public Builder setDefaultCarrierRestriction(
+        public @NonNull Builder setDefaultCarrierRestriction(
                 @CarrierRestrictionDefault int carrierRestrictionDefault) {
             mRules.mCarrierRestrictionDefault = carrierRestrictionDefault;
             return this;
@@ -391,7 +394,7 @@
          *
          * @param multiSimPolicy multi SIM policy
          */
-        public Builder setMultiSimPolicy(@MultiSimPolicy int multiSimPolicy) {
+        public @NonNull Builder setMultiSimPolicy(@MultiSimPolicy int multiSimPolicy) {
             mRules.mMultiSimPolicy = multiSimPolicy;
             return this;
         }
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index b48388e..5a89ae8 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -89,11 +89,14 @@
     }
 
     /**
-     * Get the Absolute Radio Frequency Channel Number.
+     * Get the New Radio Absolute Radio Frequency Channel Number.
+     *
+     * Reference: 3GPP TS 38.101-1 section 5.4.2.1 NR-ARFCN and channel raster.
+     * Reference: 3GPP TS 38.101-2 section 5.4.2.1 NR-ARFCN and channel raster.
+     *
      * @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
      */
-    @Override
-    public int getChannelNumber() {
+    public int getNrarfcn() {
         return mNrArfcn;
     }
 
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index d98f37d..b9d8eb6 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -174,22 +174,22 @@
         boolean hasManifestPermission = checkManifestPermission(context, query.callingPid,
                 query.callingUid, permissionToCheck);
 
-        int appOpMode = context.getSystemService(AppOpsManager.class)
-                .noteOpNoThrow(AppOpsManager.permissionToOpCode(permissionToCheck),
-                        query.callingUid, query.callingPackage);
-
-        if (hasManifestPermission && appOpMode == AppOpsManager.MODE_ALLOWED) {
-            // If the app did everything right, return without logging.
-            return LocationPermissionResult.ALLOWED;
-        }
-
-        // If the app has the manifest permission but not the app-op permission, it means that
-        // it's aware of the requirement and the user denied permission explicitly. If we see
-        // this, don't let any of the overrides happen.
         if (hasManifestPermission) {
-            Log.i(TAG, query.callingPackage + " is aware of " + locationTypeForLog + " but the"
-                    + " app-ops permission is specifically denied.");
-            return appOpsModeToPermissionResult(appOpMode);
+            // Only check the app op if the app has the permission.
+            int appOpMode = context.getSystemService(AppOpsManager.class)
+                    .noteOpNoThrow(AppOpsManager.permissionToOpCode(permissionToCheck),
+                            query.callingUid, query.callingPackage);
+            if (appOpMode == AppOpsManager.MODE_ALLOWED) {
+                // If the app did everything right, return without logging.
+                return LocationPermissionResult.ALLOWED;
+            } else {
+                // If the app has the manifest permission but not the app-op permission, it means
+                // that it's aware of the requirement and the user denied permission explicitly.
+                // If we see this, don't let any of the overrides happen.
+                Log.i(TAG, query.callingPackage + " is aware of " + locationTypeForLog + " but the"
+                        + " app-ops permission is specifically denied.");
+                return appOpsModeToPermissionResult(appOpMode);
+            }
         }
 
         int minSdkVersion = Manifest.permission.ACCESS_FINE_LOCATION.equals(permissionToCheck)
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 9614dc5..a6c81db 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -17,11 +17,13 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.TelephonyManager.NetworkType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -140,6 +142,7 @@
     @ServiceState.RoamingType
     private int mRoamingType;
 
+    @NetworkType
     private int mAccessNetworkTechnology;
 
     @NRStatus
@@ -149,6 +152,7 @@
 
     private final boolean mEmergencyOnly;
 
+    @ServiceType
     private final int[] mAvailableServices;
 
     @Nullable
@@ -167,9 +171,8 @@
      * @param regState Network registration state. Must be one of the {@link RegState}. For
      * {@link TransportType#WLAN} transport, only {@link #REG_STATE_HOME} and
      * {@link #REG_STATE_NOT_REG_NOT_SEARCHING} are valid states.
-     * @param accessNetworkTechnology Access network technology. Must be one of TelephonyManager
-     * NETWORK_TYPE_XXXX. For {@link TransportType#WLAN} transport, set to
-     * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
+     * @param accessNetworkTechnology Access network technology.For {@link TransportType#WLAN}
+     * transport, set to {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
      * @param rejectCause Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
      * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
      * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA. If
@@ -182,8 +185,9 @@
      * information is not available.
      */
     public NetworkRegistrationState(@Domain int domain, int transportType, @RegState int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
+                                    @NetworkType int accessNetworkTechnology, int rejectCause,
+                                    boolean emergencyOnly,
+                                    @NonNull @ServiceType int[] availableServices,
                                     @Nullable CellIdentity cellIdentity) {
         mDomain = domain;
         mTransportType = transportType;
@@ -230,7 +234,7 @@
         updateNrStatus(mDataSpecificStates);
     }
 
-    protected NetworkRegistrationState(Parcel source) {
+    private NetworkRegistrationState(Parcel source) {
         mDomain = source.readInt();
         mTransportType = source.readInt();
         mRegState = source.readInt();
@@ -285,6 +289,14 @@
     }
 
     /**
+     * @hide
+     * @return {@code true} if in service.
+     */
+    public boolean isInService() {
+        return mRegState == REG_STATE_HOME || mRegState == REG_STATE_ROAMING;
+    }
+
+    /**
      * Set {@link ServiceState.RoamingType roaming type}. This could override
      * roaming type based on resource overlay or carrier config.
      * @hide
@@ -309,25 +321,29 @@
     /**
      * @return List of available service types.
      */
+    @NonNull
+    @ServiceType
     public int[] getAvailableServices() { return mAvailableServices; }
 
     /**
-     * @return The access network technology {@link TelephonyManager.NetworkType}.
+     * @return The access network technology {@link NetworkType}.
      */
-    public @TelephonyManager.NetworkType int getAccessNetworkTechnology() {
+    public @NetworkType int getAccessNetworkTechnology() {
         return mAccessNetworkTechnology;
     }
 
     /**
-     * override the access network technology {@link TelephonyManager.NetworkType} e.g, rat ratchet.
+     * override the access network technology {@link NetworkType} e.g, rat ratchet.
      * @hide
      */
-    public void setAccessNetworkTechnology(@TelephonyManager.NetworkType int tech) {
+    public void setAccessNetworkTechnology(@NetworkType int tech) {
         mAccessNetworkTechnology = tech;
     }
 
     /**
-     * @return Network reject cause
+     * @return Reason for denial if the registration state is {@link #REG_STATE_DENIED}.
+     * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
+     * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA
      */
     public int getRejectCause() {
         return mRejectCause;
@@ -336,6 +352,7 @@
     /**
      * @return The cell information.
      */
+    @Nullable
     public CellIdentity getCellIdentity() {
         return mCellIdentity;
     }
@@ -539,4 +556,192 @@
         p.recycle();
         return result;
     }
+
+    /**
+     * Provides a convenient way to set the fields of a {@link NetworkRegistrationState} when
+     * creating a new instance.
+     *
+     * <p>The example below shows how you might create a new {@code NetworkRegistrationState}:
+     *
+     * <pre><code>
+     *
+     * NetworkRegistrationState nrs = new NetworkRegistrationState.Builder()
+     *     .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS)
+     *     .setApnName("apn.example.com")
+     *     .setEntryName("Example Carrier APN")
+     *     .setMmsc(Uri.parse("http://mms.example.com:8002"))
+     *     .setMmsProxyAddress(mmsProxy)
+     *     .setMmsProxyPort(8799)
+     *     .build();
+     * </code></pre>
+     */
+    public static class Builder{
+        @Domain
+        private int mDomain;
+
+        private int mTransportType;
+
+        @RegState
+        private int mRegState;
+
+        @ServiceState.RoamingType
+        private int mRoamingType;
+
+        @NetworkType
+        private int mAccessNetworkTechnology;
+
+        @NRStatus
+        private int mNrStatus;
+
+        private int mRejectCause;
+
+        private boolean mEmergencyOnly;
+
+        @ServiceType
+        private int[] mAvailableServices;
+
+        @Nullable
+        private CellIdentity mCellIdentity;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {}
+
+        /**
+         * Set the network domain.
+         *
+         * @param domain Network domain.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setDomain(@Domain int domain) {
+            mDomain = domain;
+            return this;
+        }
+
+        /**
+         * Set the transport type.
+         *
+         * @param transportType Transport type.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setTransportType(int transportType) {
+            mTransportType = transportType;
+            return this;
+        }
+
+        /**
+         * Set the registration state.
+         *
+         * @param regState The registration state.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setRegState(@RegState int regState) {
+            mRegState = regState;
+            return this;
+        }
+
+        /**
+         * Set the roaming type.
+         *
+         * @param roamingType Roaming type.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setRoamingType(@ServiceState.RoamingType int roamingType) {
+            mRoamingType = roamingType;
+            return this;
+        }
+
+        /**
+         * Set tne access network technology.
+         *
+         * @return The same instance of the builder.
+         *
+         * @param accessNetworkTechnology The access network technology
+         */
+        public @NonNull Builder setAccessNetworkTechnology(
+                @NetworkType int accessNetworkTechnology) {
+            mAccessNetworkTechnology = accessNetworkTechnology;
+            return this;
+        }
+
+        /**
+         * Set the 5G NR connection status.
+         *
+         * @param nrStatus 5G NR connection status.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setNrStatus(@NRStatus int nrStatus) {
+            mNrStatus = nrStatus;
+            return this;
+        }
+
+        /**
+         * Set the network reject cause.
+         *
+         * @param rejectCause Reason for denial if the registration state is
+         * {@link #REG_STATE_DENIED}.Depending on {@code accessNetworkTechnology}, the values are
+         * defined in 3GPP TS 24.008 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2
+         * A.S0001 6.2.2.44 for CDMA. If the reject cause is not supported or unknown, set it to 0.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setRejectCause(int rejectCause) {
+            mRejectCause = rejectCause;
+            return this;
+        }
+
+        /**
+         * Set emergency only.
+         *
+         * @param emergencyOnly True if this network registration is for emergency use only.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
+            mEmergencyOnly = emergencyOnly;
+            return this;
+        }
+
+        /**
+         * Set the available services.
+         *
+         * @param availableServices Available services.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setAvailableServices(
+                @NonNull @ServiceType int[] availableServices) {
+            mAvailableServices = availableServices;
+            return this;
+        }
+
+        /**
+         * Set the cell identity.
+         *
+         * @param cellIdentity The cell identity.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
+            mCellIdentity = cellIdentity;
+            return this;
+        }
+
+        /**
+         * Build the NetworkRegistrationState.
+         *
+         * @return the NetworkRegistrationState object.
+         */
+        public @NonNull NetworkRegistrationState build() {
+            return new NetworkRegistrationState(mDomain, mTransportType, mRegState,
+                    mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
+                    mCellIdentity);
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index bec9494..f1240e9 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
@@ -82,27 +83,30 @@
      * service is associated with one physical SIM slot.
      */
     public abstract class NetworkServiceProvider implements AutoCloseable {
-        private final int mSlotId;
+        private final int mSlotIndex;
 
         private final List<INetworkServiceCallback>
                 mNetworkRegistrationStateChangedCallbacks = new ArrayList<>();
 
-        public NetworkServiceProvider(int slotId) {
-            mSlotId = slotId;
+        /**
+         * Constructor
+         * @param slotIndex SIM slot id the data service provider associated with.
+         */
+        public NetworkServiceProvider(int slotIndex) {
+            mSlotIndex = slotIndex;
         }
 
         /**
-         * @return SIM slot id the network service associated with.
+         * @return SIM slot index the network service associated with.
          */
-        public final int getSlotId() {
-            return mSlotId;
+        public final int getSlotIndex() {
+            return mSlotIndex;
         }
 
         /**
          * API to get network registration state. The result will be passed to the callback.
          * @param domain Network domain
          * @param callback The callback for reporting network registration state
-         * @return SIM slot id the network service associated with.
          */
         public void getNetworkRegistrationState(@Domain int domain,
                                                 @NonNull NetworkServiceCallback callback) {
@@ -110,9 +114,12 @@
                     NetworkServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
         }
 
+        /**
+         * Notify the system that network registration state is changed.
+         */
         public final void notifyNetworkRegistrationStateChanged() {
             mHandler.obtainMessage(NETWORK_SERVICE_INDICATION_NETWORK_STATE_CHANGED,
-                    mSlotId, 0, null).sendToTarget();
+                    mSlotIndex, 0, null).sendToTarget();
         }
 
         private void registerForStateChanged(@NonNull INetworkServiceCallback callback) {
@@ -154,23 +161,23 @@
 
         @Override
         public void handleMessage(Message message) {
-            final int slotId = message.arg1;
+            final int slotIndex = message.arg1;
             final INetworkServiceCallback callback = (INetworkServiceCallback) message.obj;
 
-            NetworkServiceProvider serviceProvider = mServiceMap.get(slotId);
+            NetworkServiceProvider serviceProvider = mServiceMap.get(slotIndex);
 
             switch (message.what) {
                 case NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER:
                     // If the service provider doesn't exist yet, we try to create it.
                     if (serviceProvider == null) {
-                        mServiceMap.put(slotId, createNetworkServiceProvider(slotId));
+                        mServiceMap.put(slotIndex, onCreateNetworkServiceProvider(slotIndex));
                     }
                     break;
                 case NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER:
                     // If the service provider doesn't exist yet, we try to create it.
                     if (serviceProvider != null) {
                         serviceProvider.close();
-                        mServiceMap.remove(slotId);
+                        mServiceMap.remove(slotIndex);
                     }
                     break;
                 case NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS:
@@ -223,12 +230,12 @@
      * this method to facilitate the creation of {@link NetworkServiceProvider} instances. The system
      * will call this method after binding the network service for each active SIM slot id.
      *
-     * @param slotId SIM slot id the network service associated with.
+     * @param slotIndex SIM slot id the network service associated with.
      * @return Network service object
      */
-    protected abstract NetworkServiceProvider createNetworkServiceProvider(int slotId);
+    @Nullable
+    public abstract NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex);
 
-    /** @hide */
     @Override
     public IBinder onBind(Intent intent) {
         if (intent == null || !NETWORK_SERVICE_INTERFACE.equals(intent.getAction())) {
@@ -239,7 +246,6 @@
         return mBinder;
     }
 
-    /** @hide */
     @Override
     public boolean onUnbind(Intent intent) {
         mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_ALL_NETWORK_SERVICE_PROVIDERS, 0,
@@ -252,6 +258,7 @@
     @Override
     public void onDestroy() {
         mHandlerThread.quit();
+        super.onDestroy();
     }
 
     /**
@@ -261,35 +268,35 @@
     private class INetworkServiceWrapper extends INetworkService.Stub {
 
         @Override
-        public void createNetworkServiceProvider(int slotId) {
-            mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotId,
+        public void createNetworkServiceProvider(int slotIndex) {
+            mHandler.obtainMessage(NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER, slotIndex,
                     0, null).sendToTarget();
         }
 
         @Override
-        public void removeNetworkServiceProvider(int slotId) {
-            mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotId,
+        public void removeNetworkServiceProvider(int slotIndex) {
+            mHandler.obtainMessage(NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER, slotIndex,
                     0, null).sendToTarget();
         }
 
         @Override
         public void getNetworkRegistrationState(
-                int slotId, int domain, INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_STATE, slotId,
+                int slotIndex, int domain, INetworkServiceCallback callback) {
+            mHandler.obtainMessage(NETWORK_SERVICE_GET_REGISTRATION_STATE, slotIndex,
                     domain, callback).sendToTarget();
         }
 
         @Override
         public void registerForNetworkRegistrationStateChanged(
-                int slotId, INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE, slotId,
+                int slotIndex, INetworkServiceCallback callback) {
+            mHandler.obtainMessage(NETWORK_SERVICE_REGISTER_FOR_STATE_CHANGE, slotIndex,
                     0, callback).sendToTarget();
         }
 
         @Override
         public void unregisterForNetworkRegistrationStateChanged(
-                int slotId,INetworkServiceCallback callback) {
-            mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE, slotId,
+                int slotIndex, INetworkServiceCallback callback) {
+            mHandler.obtainMessage(NETWORK_SERVICE_UNREGISTER_FOR_STATE_CHANGE, slotIndex,
                     0, callback).sendToTarget();
         }
     }
diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java
index dbad02f..c2fcfb7 100644
--- a/telephony/java/android/telephony/NetworkServiceCallback.java
+++ b/telephony/java/android/telephony/NetworkServiceCallback.java
@@ -17,6 +17,7 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.NetworkService.NetworkServiceProvider;
@@ -75,7 +76,8 @@
      *                {@link NetworkServiceCallback#RESULT_ERROR_UNSUPPORTED}
      * @param state The state information to be returned to callback.
      */
-    public void onGetNetworkRegistrationStateComplete(int result, NetworkRegistrationState state) {
+    public void onGetNetworkRegistrationStateComplete(int result,
+                                                      @Nullable NetworkRegistrationState state) {
         INetworkServiceCallback callback = mCallback.get();
         if (callback != null) {
             try {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 5fd36f4..918bf60 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -292,17 +292,16 @@
     public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
 
     /**
-     *  Listen for changes to active data subId. Active data subscription
-     *  is whichever is being used for Internet data. For most of the case, it's
-     *  default data subscription but it could be others. For example, when data is
-     *  switched to opportunistic subscription, that becomes the active data sub.
+     *  Listen for changes to active data subId. Active data subscription is
+     *  the current subscription used to setup Cellular Internet data. For example,
+     *  it could be the current active opportunistic subscription in use, or the
+     *  subscription user selected as default data subscription in DSDS mode.
      *
      *  Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
      *  READ_PHONE_STATE}
-     *  @see #onActiveDataSubIdChanged
-     *  @hide
+     *  @see #onActiveDataSubscriptionIdChanged
      */
-    public static final int LISTEN_ACTIVE_DATA_SUBID_CHANGE               = 0x00400000;
+    public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000;
 
     /**
      *  Listen for changes to the radio power state.
@@ -709,12 +708,11 @@
     /**
      * Callback invoked when active data subId changes. Requires
      * the READ_PHONE_STATE permission.
-     * @param subId current data subId used for Internet data. It will be default data subscription
-     *              most cases. And it could be other subscriptions for example opportunistic
-     *              subscription if data is switched onto it.
-     * @hide
+     * @param subId current subscription used to setup Cellular Internet data.
+     *              For example, it could be the current active opportunistic subscription in use,
+     *              or the subscription user selected as default data subscription in DSDS mode.
      */
-    public void onActiveDataSubIdChanged(int subId) {
+    public void onActiveDataSubscriptionIdChanged(int subId) {
         // default implementation empty
     }
 
@@ -1003,7 +1001,7 @@
             if (psl == null) return;
 
             Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(() -> psl.onActiveDataSubIdChanged(subId)));
+                    () -> mExecutor.execute(() -> psl.onActiveDataSubscriptionIdChanged(subId)));
         }
 
         public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) {
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 4fdfcbe0..48c07e8 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -22,6 +22,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.TelephonyManager.PrefNetworkMode;
 
 import com.android.internal.telephony.RILConstants;
 
@@ -170,7 +171,8 @@
     };
 
     @UnsupportedAppUsage
-    public static int getRafFromNetworkType(int type) {
+    @TelephonyManager.NetworkTypeBitMask
+    public static int getRafFromNetworkType(@PrefNetworkMode int type) {
         switch (type) {
             case RILConstants.NETWORK_MODE_WCDMA_PREF:
                 return GSM | WCDMA;
@@ -279,6 +281,7 @@
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
+    @PrefNetworkMode
     public static int getNetworkTypeFromRaf(int raf) {
         raf = getAdjustedRaf(raf);
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 683905e..bddf978 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -438,7 +438,11 @@
 
     /**
      * Construct a ServiceState object from the given parcel.
+     *
+     * @deprecated The constructor takes parcel should not be public at the beginning. Use
+     * {@link #ServiceState()} instead.
      */
+    @Deprecated
     public ServiceState(Parcel in) {
         mVoiceRegState = in.readInt();
         mDataRegState = in.readInt();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index c516d97..480c9d9 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -214,7 +214,7 @@
      * @see android.telephony#CellSignalStrengthCdma
      * @see android.telephony#CellSignalStrengthGsm
      */
-    public @NonNull List<CellSignalStrength> getCellSignalStrengths() {
+    @NonNull public List<CellSignalStrength> getCellSignalStrengths() {
         return getCellSignalStrengths(CellSignalStrength.class);
     }
 
@@ -240,7 +240,7 @@
      * @see android.telephony#CellSignalStrengthCdma
      * @see android.telephony#CellSignalStrengthGsm
      */
-    public <T extends CellSignalStrength> @NonNull List<T> getCellSignalStrengths(
+    @NonNull public <T extends CellSignalStrength> List<T> getCellSignalStrengths(
             @NonNull Class<T> clazz) {
         List<T> cssList = new ArrayList<>(2); // Usually have 2 or fewer elems
         if (mLte.isValid() && clazz.isAssignableFrom(CellSignalStrengthLte.class)) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d7a0e50..8edc5b4 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2600,7 +2600,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
-            @NonNull @CallbackExecutor Executor executor, Consumer<Integer> callback) {
+            @Nullable @CallbackExecutor Executor executor, @Nullable  Consumer<Integer> callback) {
         if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -2609,10 +2609,11 @@
             ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
                 @Override
                 public void onComplete(int result) {
+                    if (executor == null || callback == null) {
+                        return;
+                    }
                     Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
-                        if (callback != null) {
-                            callback.accept(result);
-                        }
+                        callback.accept(result);
                     }));
                 }
             };
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 79c7195..04f3c6b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -81,6 +81,7 @@
 import com.android.internal.telephony.INumberVerificationCallback;
 import com.android.internal.telephony.IOns;
 import com.android.internal.telephony.IPhoneSubInfo;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.OperatorInfo;
@@ -98,6 +99,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -1566,6 +1568,7 @@
      * Returns the Type Allocation Code from the IMEI. Return null if Type Allocation Code is not
      * available.
      */
+    @Nullable
     public String getTypeAllocationCode() {
         return getTypeAllocationCode(getSlotIndex());
     }
@@ -1576,6 +1579,7 @@
      *
      * @param slotIndex of which Type Allocation Code is returned
      */
+    @Nullable
     public String getTypeAllocationCode(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -1636,6 +1640,7 @@
      * Returns the Manufacturer Code from the MEID. Return null if Manufacturer Code is not
      * available.
      */
+    @Nullable
     public String getManufacturerCode() {
         return getManufacturerCode(getSlotIndex());
     }
@@ -1646,6 +1651,7 @@
      *
      * @param slotIndex of which Type Allocation Code is returned
      */
+    @Nullable
     public String getManufacturerCode(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
@@ -2797,8 +2803,8 @@
      * (see {@link #hasCarrierPrivileges}).
      * <p>
      * These "secret codes" are used to activate developer menus by dialing certain codes.
-     * And they are of the form {@code *#*#&lt;code&gt;#*#*}. The intent will have the data
-     * URI: {@code android_secret_code://&lt;code&gt;}. It is possible that a manifest
+     * And they are of the form {@code *#*#<code>#*#*}. The intent will have the data
+     * URI: {@code android_secret_code://<code>}. It is possible that a manifest
      * receiver would be woken up even if it is not currently running.
      * <p>
      * It is supposed to replace {@link android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION}
@@ -6005,6 +6011,7 @@
      * @return IMS Service Table or null if not present or not loaded
      * @hide
      */
+    @Nullable
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getIsimIst() {
@@ -6856,12 +6863,12 @@
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId the id of the subscription to set the preferred network type for.
-     * @param networkType the preferred network type, defined in RILConstants.java.
+     * @param networkType the preferred network type
      * @return true on success; false on any failure.
      * @hide
      */
     @UnsupportedAppUsage
-    public boolean setPreferredNetworkType(int subId, int networkType) {
+    public boolean setPreferredNetworkType(int subId, @PrefNetworkMode int networkType) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
@@ -10180,21 +10187,40 @@
      * @param subId which opportunistic subscription
      * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
      * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
-     * @return true if request is accepted, else false.
+     * @param needValidation whether validation is needed before switch happens.
+     * @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}
+     *                 for more details. Pass null if don't care about the result.
      *
      */
-    public boolean setPreferredOpportunisticDataSubscription(int subId) {
+    public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
+            @Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         try {
             IOns iOpportunisticNetworkService = getIOns();
-            if (iOpportunisticNetworkService != null) {
-                return iOpportunisticNetworkService
-                        .setPreferredDataSubscriptionId(subId, pkgForDebug);
+            if (iOpportunisticNetworkService == null) {
+                return;
             }
+            ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+                @Override
+                public void onComplete(int result) {
+                    if (executor == null || callback == null) {
+                        return;
+                    }
+                    Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                        callback.accept(result);
+                    }));
+                }
+            };
+
+            iOpportunisticNetworkService
+                    .setPreferredDataSubscriptionId(subId, needValidation, callbackStub,
+                            pkgForDebug);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "setPreferredDataSubscriptionId RemoteException", ex);
         }
-        return false;
+        return;
     }
 
     /**
@@ -10361,18 +10387,16 @@
      * <p>Requires Permission:
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
      * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * Note: with only carrier privileges, it is not allowed to switch from multi-sim
+     * to single-sim
+     *
      * @param numOfSims number of live SIMs we want to switch to
      * @throws android.os.RemoteException
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void switchMultiSimConfig(int numOfSims) {
-        //only proceed if multi-sim is not restricted
-        if (!isMultisimSupported()) {
-            Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted or not supported.");
-            return;
-        }
-
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a4ed775..0b1d1fb 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.content.ContentValues;
 import android.database.Cursor;
-import android.hardware.radio.V1_0.ApnTypes;
+import android.hardware.radio.V1_4.ApnTypes;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -61,6 +61,7 @@
     private static final String V4_FORMAT_REGEX = "^\\[ApnSettingV4\\]\\s*";
     private static final String V5_FORMAT_REGEX = "^\\[ApnSettingV5\\]\\s*";
     private static final String V6_FORMAT_REGEX = "^\\[ApnSettingV6\\]\\s*";
+    private static final String V7_FORMAT_REGEX = "^\\[ApnSettingV7\\]\\s*";
 
     /**
      * Default value for mtu if it's not set. Moved from PhoneConstants.
@@ -79,7 +80,7 @@
      * APN type for all APNs.
      * @hide
      */
-    public static final int TYPE_ALL = ApnTypes.ALL;
+    public static final int TYPE_ALL = ApnTypes.ALL | ApnTypes.MCX;
     /** APN type for default data traffic. */
     public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI;
     /** APN type for MMS traffic. */
@@ -103,6 +104,8 @@
      * for access to carrier services in an emergency call situation.
      */
     public static final int TYPE_EMERGENCY = ApnTypes.EMERGENCY;
+    /** APN type for MCX (Mission Critical Service) where X can be PTT/Video/Data */
+    public static final int TYPE_MCX = ApnTypes.MCX;
 
     /** @hide */
     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
@@ -115,7 +118,8 @@
         TYPE_IMS,
         TYPE_CBS,
         TYPE_IA,
-        TYPE_EMERGENCY
+        TYPE_EMERGENCY,
+        TYPE_MCX
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApnType {}
@@ -206,6 +210,7 @@
         APN_TYPE_STRING_MAP.put("cbs", TYPE_CBS);
         APN_TYPE_STRING_MAP.put("ia", TYPE_IA);
         APN_TYPE_STRING_MAP.put("emergency", TYPE_EMERGENCY);
+        APN_TYPE_STRING_MAP.put("mcx", TYPE_MCX);
         APN_TYPE_INT_MAP = new ArrayMap<Integer, String>();
         APN_TYPE_INT_MAP.put(TYPE_DEFAULT, "default");
         APN_TYPE_INT_MAP.put(TYPE_MMS, "mms");
@@ -217,6 +222,7 @@
         APN_TYPE_INT_MAP.put(TYPE_CBS, "cbs");
         APN_TYPE_INT_MAP.put(TYPE_IA, "ia");
         APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, "emergency");
+        APN_TYPE_INT_MAP.put(TYPE_MCX, "mcx");
 
         PROTOCOL_STRING_MAP = new ArrayMap<String, Integer>();
         PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
@@ -281,6 +287,8 @@
     private boolean mPermanentFailed = false;
     private final int mCarrierId;
 
+    private final int mSkip464Xlat;
+
     /**
      * Returns the MTU size of the mobile interface to which the APN connected.
      *
@@ -618,6 +626,17 @@
         return mCarrierId;
     }
 
+    /**
+     * Returns the skip464xlat flag for this APN.
+     *
+     * @return SKIP_464XLAT_DEFAULT, SKIP_464XLAT_DISABLE or SKIP_464XLAT_ENABLE
+     * @hide
+     */
+    @Carriers.Skip464XlatStatus
+    public int getSkip464Xlat() {
+        return mSkip464Xlat;
+    }
+
     private ApnSetting(Builder builder) {
         this.mEntryName = builder.mEntryName;
         this.mApnName = builder.mApnName;
@@ -646,6 +665,7 @@
         this.mMvnoMatchData = builder.mMvnoMatchData;
         this.mApnSetId = builder.mApnSetId;
         this.mCarrierId = builder.mCarrierId;
+        this.mSkip464Xlat = builder.mSkip464Xlat;
     }
 
     /**
@@ -657,7 +677,7 @@
             int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
             boolean carrierEnabled, int networkTypeBitmask, int profileId,
             boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu,
-            int mvnoType, String mvnoMatchData, int apnSetId, int carrierId) {
+            int mvnoType, String mvnoMatchData, int apnSetId, int carrierId, int skip464xlat) {
         return new Builder()
             .setId(id)
             .setOperatorNumeric(operatorNumeric)
@@ -686,6 +706,7 @@
             .setMvnoMatchData(mvnoMatchData)
             .setApnSetId(apnSetId)
             .setCarrierId(carrierId)
+            .setSkip464Xlat(skip464xlat)
             .buildWithoutCheck();
     }
 
@@ -703,7 +724,8 @@
             mmsc, mmsProxyAddress, mmsProxyPort, user, password, authType, mApnTypeBitmask,
             protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, profileId,
             modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType, mvnoMatchData,
-            Carriers.NO_APN_SET_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+            Carriers.NO_APN_SET_ID, TelephonyManager.UNKNOWN_CARRIER_ID,
+            Carriers.SKIP_464XLAT_DEFAULT);
     }
 
     /**
@@ -762,7 +784,8 @@
             cursor.getString(cursor.getColumnIndexOrThrow(
                 Telephony.Carriers.MVNO_MATCH_DATA)),
             cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)),
-            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)));
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.SKIP_464XLAT)));
     }
 
     /**
@@ -775,7 +798,7 @@
             apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
             apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
             apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId,
-            apn.mCarrierId);
+            apn.mCarrierId, apn.mSkip464Xlat);
     }
 
     /**
@@ -824,6 +847,13 @@
      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
      *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>
      *
+     * v7 format:
+     *   [ApnSettingV7] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
+     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
+     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
+     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
+     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>, <skip464xlat>
+     *
      * Note that the strings generated by {@link #toString()} do not contain the username
      * and password and thus cannot be read by this method.
      *
@@ -836,7 +866,10 @@
 
         int version;
         // matches() operates on the whole string, so append .* to the regex.
-        if (data.matches(V6_FORMAT_REGEX + ".*")) {
+        if (data.matches(V7_FORMAT_REGEX + ".*")) {
+            version = 7;
+            data = data.replaceFirst(V7_FORMAT_REGEX, "");
+        } else if (data.matches(V6_FORMAT_REGEX + ".*")) {
             version = 6;
             data = data.replaceFirst(V6_FORMAT_REGEX, "");
         } else if (data.matches(V5_FORMAT_REGEX + ".*")) {
@@ -882,6 +915,7 @@
         String mvnoMatchData = "";
         int apnSetId = Carriers.NO_APN_SET_ID;
         int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        int skip464xlat = Carriers.SKIP_464XLAT_DEFAULT;
         if (version == 1) {
             typeArray = new String[a.length - 13];
             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
@@ -928,6 +962,12 @@
             if (a.length > 28) {
                 carrierId = Integer.parseInt(a[28]);
             }
+            if (a.length > 29) {
+                try {
+                    skip464xlat = Integer.parseInt(a[29]);
+                } catch (NumberFormatException e) {
+                }
+            }
         }
 
         // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
@@ -943,7 +983,7 @@
             getProtocolIntFromString(protocol), getProtocolIntFromString(roamingProtocol),
             carrierEnabled, networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime,
             maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId,
-            carrierId);
+            carrierId, skip464xlat);
     }
 
     /**
@@ -979,7 +1019,7 @@
      */
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("[ApnSettingV6] ")
+        sb.append("[ApnSettingV7] ")
                 .append(mEntryName)
                 .append(", ").append(mId)
                 .append(", ").append(mOperatorNumeric)
@@ -1007,6 +1047,7 @@
         sb.append(", ").append(mNetworkTypeBitmask);
         sb.append(", ").append(mApnSetId);
         sb.append(", ").append(mCarrierId);
+        sb.append(", ").append(mSkip464Xlat);
         return sb.toString();
     }
 
@@ -1100,7 +1141,8 @@
             && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
             && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
             && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId);
+            && Objects.equals(mCarrierId, other.mCarrierId)
+            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1146,7 +1188,8 @@
             && Objects.equals(mMvnoType, other.mMvnoType)
             && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
             && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId);
+            && Objects.equals(mCarrierId, other.mCarrierId)
+            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     /**
@@ -1174,7 +1217,8 @@
             && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
             && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
             && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId);
+            && Objects.equals(mCarrierId, other.mCarrierId)
+            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
     }
 
     // Equal or one is null.
@@ -1221,6 +1265,7 @@
         apnValue.put(Telephony.Carriers.MVNO_TYPE, getMvnoTypeStringFromInt(mMvnoType));
         apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask);
         apnValue.put(Telephony.Carriers.CARRIER_ID, mCarrierId);
+        apnValue.put(Telephony.Carriers.SKIP_464XLAT, mSkip464Xlat);
 
         return apnValue;
     }
@@ -1380,6 +1425,7 @@
         dest.writeInt(mNetworkTypeBitmask);
         dest.writeInt(mApnSetId);
         dest.writeInt(mCarrierId);
+        dest.writeInt(mSkip464Xlat);
     }
 
     private static ApnSetting readFromParcel(Parcel in) {
@@ -1403,11 +1449,12 @@
         final int networkTypeBitmask = in.readInt();
         final int apnSetId = in.readInt();
         final int carrierId = in.readInt();
+        final int skip464xlat = in.readInt();
 
         return makeApnSetting(id, operatorNumeric, entryName, apnName,
-            proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
-            protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
-            0, 0, 0, 0, mvnoType, null, apnSetId, carrierId);
+                proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
+                protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
+                0, 0, 0, 0, mvnoType, null, apnSetId, carrierId, skip464xlat);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<ApnSetting> CREATOR =
@@ -1484,6 +1531,7 @@
         private String mMvnoMatchData;
         private int mApnSetId;
         private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        private int mSkip464Xlat = Carriers.SKIP_464XLAT_DEFAULT;
 
         /**
          * Default constructor for Builder.
@@ -1820,12 +1868,24 @@
          *
          * @param carrierId the carrier id to set for this APN
          */
+        @NonNull
         public Builder setCarrierId(int carrierId) {
             this.mCarrierId = carrierId;
             return this;
         }
 
         /**
+         * Sets skip464xlat flag for this APN.
+         *
+         * @param skip464xlat skip464xlat for this APN
+         * @hide
+         */
+        public Builder setSkip464Xlat(@Carriers.Skip464XlatStatus int skip464xlat) {
+            this.mSkip464Xlat = skip464xlat;
+            return this;
+        }
+
+        /**
          * Builds {@link ApnSetting} from this builder.
          *
          * @return {@code null} if {@link #setApnName(String)} or {@link #setEntryName(String)}
@@ -1833,7 +1893,7 @@
          * {@link ApnSetting} built from this builder otherwise.
          */
         public ApnSetting build() {
-            if ((mApnTypeBitmask & ApnTypes.ALL) == 0 || TextUtils.isEmpty(mApnName)
+            if ((mApnTypeBitmask & TYPE_ALL) == 0 || TextUtils.isEmpty(mApnName)
                 || TextUtils.isEmpty(mEntryName)) {
                 return null;
             }
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 6024143..0622cdd 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -25,6 +25,8 @@
 import android.os.Parcelable;
 import android.telephony.data.ApnSetting.ProtocolType;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.List;
@@ -90,6 +92,8 @@
         mMtu = mtu;
     }
 
+    /** @hide */
+    @VisibleForTesting
     public DataCallResponse(Parcel source) {
         mStatus = source.readInt();
         mSuggestedRetryTime = source.readInt();
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index f45954b..332aae1 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -19,6 +19,8 @@
 import static android.telephony.data.ApnSetting.ProtocolType;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Build;
 import android.os.Parcel;
@@ -158,6 +160,7 @@
     /**
      * @return The APN to establish data connection.
      */
+    @NonNull
     public String getApn() { return mApn; }
 
     /**
@@ -173,11 +176,13 @@
     /**
      * @return The username for APN. Can be null.
      */
+    @Nullable
     public String getUserName() { return mUserName; }
 
     /**
      * @return The password for APN. Can be null.
      */
+    @Nullable
     public String getPassword() { return mPassword; }
 
     /**
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index a3fa77b..59d1e1e 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -116,23 +116,23 @@
      */
     public abstract class DataServiceProvider implements AutoCloseable {
 
-        private final int mSlotId;
+        private final int mSlotIndex;
 
         private final List<IDataServiceCallback> mDataCallListChangedCallbacks = new ArrayList<>();
 
         /**
          * Constructor
-         * @param slotId SIM slot id the data service provider associated with.
+         * @param slotIndex SIM slot index the data service provider associated with.
          */
-        public DataServiceProvider(int slotId) {
-            mSlotId = slotId;
+        public DataServiceProvider(int slotIndex) {
+            mSlotIndex = slotIndex;
         }
 
         /**
-         * @return SIM slot id the data service provider associated with.
+         * @return SIM slot index the data service provider associated with.
          */
-        public final int getSlotId() {
-            return mSlotId;
+        public final int getSlotIndex() {
+            return mSlotIndex;
         }
 
         /**
@@ -251,9 +251,9 @@
         public final void notifyDataCallListChanged(List<DataCallResponse> dataCallList) {
             synchronized (mDataCallListChangedCallbacks) {
                 for (IDataServiceCallback callback : mDataCallListChangedCallbacks) {
-                    mHandler.obtainMessage(DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED, mSlotId,
-                            0, new DataCallListChangedIndication(dataCallList, callback))
-                            .sendToTarget();
+                    mHandler.obtainMessage(DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED,
+                            mSlotIndex, 0, new DataCallListChangedIndication(dataCallList,
+                                    callback)).sendToTarget();
                 }
             }
         }
@@ -342,20 +342,20 @@
         @Override
         public void handleMessage(Message message) {
             IDataServiceCallback callback;
-            final int slotId = message.arg1;
-            DataServiceProvider serviceProvider = mServiceMap.get(slotId);
+            final int slotIndex = message.arg1;
+            DataServiceProvider serviceProvider = mServiceMap.get(slotIndex);
 
             switch (message.what) {
                 case DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER:
-                    serviceProvider = createDataServiceProvider(message.arg1);
+                    serviceProvider = onCreateDataServiceProvider(message.arg1);
                     if (serviceProvider != null) {
-                        mServiceMap.put(slotId, serviceProvider);
+                        mServiceMap.put(slotIndex, serviceProvider);
                     }
                     break;
                 case DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER:
                     if (serviceProvider != null) {
                         serviceProvider.close();
-                        mServiceMap.remove(slotId);
+                        mServiceMap.remove(slotIndex);
                     }
                     break;
                 case DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS:
@@ -454,12 +454,12 @@
      * this method to facilitate the creation of {@link DataServiceProvider} instances. The system
      * will call this method after binding the data service for each active SIM slot id.
      *
-     * @param slotId SIM slot id the data service associated with.
+     * @param slotIndex SIM slot id the data service associated with.
      * @return Data service object
      */
-    public abstract DataServiceProvider createDataServiceProvider(int slotId);
+    @Nullable
+    public abstract DataServiceProvider onCreateDataServiceProvider(int slotIndex);
 
-    /** @hide */
     @Override
     public IBinder onBind(Intent intent) {
         if (intent == null || !DATA_SERVICE_INTERFACE.equals(intent.getAction())) {
@@ -469,17 +469,16 @@
         return mBinder;
     }
 
-    /** @hide */
     @Override
     public boolean onUnbind(Intent intent) {
         mHandler.obtainMessage(DATA_SERVICE_REMOVE_ALL_DATA_SERVICE_PROVIDERS).sendToTarget();
         return false;
     }
 
-    /** @hide */
     @Override
     public void onDestroy() {
         mHandlerThread.quit();
+        super.onDestroy();
     }
 
     /**
@@ -487,78 +486,78 @@
      */
     private class IDataServiceWrapper extends IDataService.Stub {
         @Override
-        public void createDataServiceProvider(int slotId) {
-            mHandler.obtainMessage(DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER, slotId, 0)
+        public void createDataServiceProvider(int slotIndex) {
+            mHandler.obtainMessage(DATA_SERVICE_CREATE_DATA_SERVICE_PROVIDER, slotIndex, 0)
                     .sendToTarget();
         }
 
         @Override
-        public void removeDataServiceProvider(int slotId) {
-            mHandler.obtainMessage(DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER, slotId, 0)
+        public void removeDataServiceProvider(int slotIndex) {
+            mHandler.obtainMessage(DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER, slotIndex, 0)
                     .sendToTarget();
         }
 
         @Override
-        public void setupDataCall(int slotId, int accessNetworkType, DataProfile dataProfile,
+        public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
                                   boolean isRoaming, boolean allowRoaming, int reason,
                                   LinkProperties linkProperties, IDataServiceCallback callback) {
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotId, 0,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
                     new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
                             allowRoaming, reason, linkProperties, callback))
                     .sendToTarget();
         }
 
         @Override
-        public void deactivateDataCall(int slotId, int cid, int reason,
+        public void deactivateDataCall(int slotIndex, int cid, int reason,
                                        IDataServiceCallback callback) {
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, slotId, 0,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, slotIndex, 0,
                     new DeactivateDataCallRequest(cid, reason, callback))
                     .sendToTarget();
         }
 
         @Override
-        public void setInitialAttachApn(int slotId, DataProfile dataProfile, boolean isRoaming,
+        public void setInitialAttachApn(int slotIndex, DataProfile dataProfile, boolean isRoaming,
                                         IDataServiceCallback callback) {
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, slotId, 0,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN, slotIndex, 0,
                     new SetInitialAttachApnRequest(dataProfile, isRoaming, callback))
                     .sendToTarget();
         }
 
         @Override
-        public void setDataProfile(int slotId, List<DataProfile> dps, boolean isRoaming,
+        public void setDataProfile(int slotIndex, List<DataProfile> dps, boolean isRoaming,
                                    IDataServiceCallback callback) {
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, slotId, 0,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_SET_DATA_PROFILE, slotIndex, 0,
                     new SetDataProfileRequest(dps, isRoaming, callback)).sendToTarget();
         }
 
         @Override
-        public void getDataCallList(int slotId, IDataServiceCallback callback) {
+        public void getDataCallList(int slotIndex, IDataServiceCallback callback) {
             if (callback == null) {
                 loge("getDataCallList: callback is null");
                 return;
             }
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, slotId, 0,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_GET_DATA_CALL_LIST, slotIndex, 0,
                     callback).sendToTarget();
         }
 
         @Override
-        public void registerForDataCallListChanged(int slotId, IDataServiceCallback callback) {
+        public void registerForDataCallListChanged(int slotIndex, IDataServiceCallback callback) {
             if (callback == null) {
                 loge("registerForDataCallListChanged: callback is null");
                 return;
             }
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, slotId,
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_DATA_CALL_LIST_CHANGED, slotIndex,
                     0, callback).sendToTarget();
         }
 
         @Override
-        public void unregisterForDataCallListChanged(int slotId, IDataServiceCallback callback) {
+        public void unregisterForDataCallListChanged(int slotIndex, IDataServiceCallback callback) {
             if (callback == null) {
                 loge("unregisterForDataCallListChanged: callback is null");
                 return;
             }
-            mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED, slotId,
-                    0, callback).sendToTarget();
+            mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_DATA_CALL_LIST_CHANGED,
+                    slotIndex, 0, callback).sendToTarget();
         }
     }
 
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index bef1142..2d0cfe8 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -17,6 +17,8 @@
 package android.telephony.data;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.LinkProperties;
 import android.os.RemoteException;
@@ -74,7 +76,8 @@
      * @param result The result code. Must be one of the {@link ResultCode}.
      * @param response Setup data call response.
      */
-    public void onSetupDataCallComplete(@ResultCode int result, DataCallResponse response) {
+    public void onSetupDataCallComplete(@ResultCode int result,
+                                        @Nullable DataCallResponse response) {
         IDataServiceCallback callback = mCallback.get();
         if (callback != null) {
             try {
@@ -141,10 +144,11 @@
      * DataServiceCallback)}.
      *
      * @param result The result code. Must be one of the {@link ResultCode}.
-     * @param dataCallList List of the current active data connection.
+     * @param dataCallList List of the current active data connection. If no data call is presented,
+     * set it to an empty list.
      */
     public void onGetDataCallListComplete(@ResultCode int result,
-                                          List<DataCallResponse> dataCallList) {
+                                          @NonNull List<DataCallResponse> dataCallList) {
         IDataServiceCallback callback = mCallback.get();
         if (callback != null) {
             try {
@@ -156,11 +160,12 @@
     }
 
     /**
-     * Called to indicate that data connection list changed.
+     * Called to indicate that data connection list changed. If no data call is presented, set it to
+     * an empty list.
      *
      * @param dataCallList List of the current active data connection.
      */
-    public void onDataCallListChanged(List<DataCallResponse> dataCallList) {
+    public void onDataCallListChanged(@NonNull List<DataCallResponse> dataCallList) {
         IDataServiceCallback callback = mCallback.get();
         if (callback != null) {
             try {
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index ad34349..afbf46d 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -17,6 +17,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -429,6 +430,7 @@
      *
      * @return an EuiccManager that uses the given card ID for all calls.
      */
+    @NonNull
     public EuiccManager createForCardId(int cardId) {
         return new EuiccManager(mContext, cardId);
     }
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index 337375a..a09844d 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.CallQuality;
@@ -606,7 +607,7 @@
      *
      * @param profile updated ImsStreamMediaProfile
      */
-    public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
+    public void callSessionRttAudioIndicatorChanged(@NonNull ImsStreamMediaProfile profile) {
         try {
             mListener.callSessionRttAudioIndicatorChanged(profile);
         } catch (RemoteException e) {
@@ -619,7 +620,7 @@
      *
      * @param callQuality The new call quality
      */
-    public void callQualityChanged(CallQuality callQuality) {
+    public void callQualityChanged(@NonNull CallQuality callQuality) {
         try {
             mListener.callQualityChanged(callQuality);
         } catch (RemoteException e) {
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index ac4d17a..bdaad5b 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -86,7 +86,8 @@
      * @param message an optional message to detail the error condition more specifically.
      * @param cause the {@link Throwable} that caused this {@link ImsException} to be created.
      */
-    public ImsException(@Nullable String message, @ImsErrorCode  int code, Throwable cause) {
+    public ImsException(@Nullable String message, @ImsErrorCode  int code,
+            @Nullable Throwable cause) {
         super(getMessage(message, code), cause);
         mCode = code;
     }
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index a58f361..37b11ed 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -17,6 +17,8 @@
 package android.telephony.ims;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
@@ -124,9 +126,9 @@
      * @param callType The type of external call.
      * @param isCallheld A flag determining if the external connection is currently held.
      */
-    public ImsExternalCallState(String callId, Uri address, Uri localAddress,
-            boolean isPullable, @ExternalCallState int callState, @ExternalCallType int callType,
-            boolean isCallheld) {
+    public ImsExternalCallState(@NonNull String callId, @NonNull Uri address,
+            @Nullable Uri localAddress, boolean isPullable, @ExternalCallState int callState,
+            @ExternalCallType int callType, boolean isCallheld) {
         mCallId = getIdForString(callId);
         mAddress = address;
         mLocalAddress = localAddress;
@@ -184,14 +186,14 @@
         return mCallId;
     }
 
-    public Uri getAddress() {
+    public @NonNull Uri getAddress() {
         return mAddress;
     }
 
     /**
      * @return A {@link Uri} containing the local address from the Multiendpoint Dialog Information.
      */
-    public Uri getLocalAddress() {
+    public @Nullable Uri getLocalAddress() {
         return mLocalAddress;
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index bb85be1..58ddf21 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -21,6 +21,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
@@ -199,7 +200,7 @@
          *
          * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
          */
-        public void onUnregistered(ImsReasonInfo info) {
+        public void onUnregistered(@Nullable ImsReasonInfo info) {
         }
 
         /**
@@ -211,7 +212,7 @@
          *         transport type that has failed to handover registration to.
          * @param info A {@link ImsReasonInfo} that identifies the reason for failure.
          */
-        public void onTechnologyChangeFailed(int imsTransportType, ImsReasonInfo info) {
+        public void onTechnologyChangeFailed(int imsTransportType, @Nullable ImsReasonInfo info) {
         }
 
         /**
@@ -223,7 +224,7 @@
          *         subscription.
          * @hide
          */
-        public void onSubscriberAssociatedUriChanged(Uri[] uris) {
+        public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) {
         }
 
         /**@hide*/
@@ -294,7 +295,7 @@
          * @param capabilities The new availability of the capabilities.
          */
         public void onCapabilitiesStatusChanged(
-                MmTelFeature.MmTelCapabilities capabilities) {
+                @NonNull MmTelFeature.MmTelCapabilities capabilities) {
         }
 
         /**@hide*/
@@ -319,7 +320,7 @@
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
      * @throws IllegalArgumentException if the subscription is invalid.
      */
-    public static ImsMmTelManager createForSubscriptionId(int subId) {
+    public static @NonNull ImsMmTelManager createForSubscriptionId(int subId) {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
         }
@@ -357,7 +358,7 @@
      * reason.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void registerImsRegistrationCallback(@CallbackExecutor Executor executor,
+    public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull RegistrationCallback c) throws ImsException {
         if (c == null) {
             throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 10001bc..464db34 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -17,6 +17,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -24,6 +25,9 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Provides STK Call Control Supplementary Service information.
@@ -260,13 +264,13 @@
     public final int result;
 
     private int[] mSsInfo;
-    private ImsCallForwardInfo[] mCfInfo;
-    private ImsSsInfo[] mImsSsInfo;
+    private List<ImsCallForwardInfo> mCfInfo;
+    private List<ImsSsInfo> mImsSsInfo;
 
     /**
      * Builder for optional ImsSsData parameters.
      */
-    public static class Builder {
+    public static final class Builder {
         private ImsSsData mImsSsData;
 
         /**
@@ -301,7 +305,7 @@
          * Set the array of {@link ImsSsInfo}s that are associated with this supplementary service
          * data.
          */
-        public @NonNull Builder setSuppServiceInfo(@NonNull ImsSsInfo[] imsSsInfos) {
+        public @NonNull Builder setSuppServiceInfo(@NonNull List<ImsSsInfo> imsSsInfos) {
             mImsSsData.mImsSsInfo = imsSsInfos;
             return this;
         }
@@ -311,7 +315,7 @@
          * service data.
          */
         public @NonNull Builder setCallForwardingInfo(
-                @NonNull ImsCallForwardInfo[] imsCallForwardInfos) {
+                @NonNull List<ImsCallForwardInfo> imsCallForwardInfos) {
             mImsSsData.mCfInfo = imsCallForwardInfos;
             return this;
         }
@@ -360,8 +364,8 @@
         serviceClass = in.readInt();
         result = in.readInt();
         mSsInfo = in.createIntArray();
-        mCfInfo = (ImsCallForwardInfo[])in.readParcelableArray(this.getClass().getClassLoader());
-        mImsSsInfo = (ImsSsInfo[])in.readParcelableArray(this.getClass().getClassLoader());
+        mCfInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
+        mImsSsInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
     }
 
     public static final @android.annotation.NonNull Creator<ImsSsData> CREATOR = new Creator<ImsSsData>() {
@@ -384,8 +388,8 @@
         out.writeInt(getServiceClass());
         out.writeInt(getResult());
         out.writeIntArray(mSsInfo);
-        out.writeParcelableArray(mCfInfo, 0);
-        out.writeParcelableArray(mImsSsInfo, 0);
+        out.writeParcelableList(mCfInfo, 0);
+        out.writeParcelableList(mImsSsInfo, 0);
     }
 
     @Override
@@ -500,12 +504,12 @@
 
     /** @hide */
     public void setImsSpecificSuppServiceInfo(ImsSsInfo[] imsSsInfo) {
-        mImsSsInfo = imsSsInfo;
+        mImsSsInfo = Arrays.asList(imsSsInfo);
     }
 
     /** @hide */
     public void setCallForwardingInfo(ImsCallForwardInfo[] cfInfo) {
-        mCfInfo = cfInfo;
+        mCfInfo = Arrays.asList(cfInfo);
     }
 
     /**
@@ -524,7 +528,7 @@
 
 
         int[] result = new int[2];
-        if (mImsSsInfo == null || mImsSsInfo.length == 0) {
+        if (mImsSsInfo == null || mImsSsInfo.size() == 0) {
             Rlog.e(TAG, "getSuppServiceInfoCompat: Could not parse mImsSsInfo, returning empty "
                     + "int[]");
             return result;
@@ -535,26 +539,26 @@
         if (isTypeClir()) {
             // Assume there will only be one ImsSsInfo.
             // contains {"n","m"} parameters
-            result[0] = mImsSsInfo[0].getClirOutgoingState();
-            result[1] = mImsSsInfo[0].getClirInterrogationStatus();
+            result[0] = mImsSsInfo.get(0).getClirOutgoingState();
+            result[1] = mImsSsInfo.get(0).getClirInterrogationStatus();
             return result;
         }
         // COLR 7.31
         if (isTypeColr()) {
-            result[0] = mImsSsInfo[0].getProvisionStatus();
+            result[0] = mImsSsInfo.get(0).getProvisionStatus();
         }
         // Facility Lock CLCK 7.4 (for call barring), CLIP 7.6, COLP 7.8, as well as any
         // other result, just return the status for the "n" parameter and provisioning status for
         // "m" as the default.
-        result[0] = mImsSsInfo[0].getStatus();
-        result[1] = mImsSsInfo[0].getProvisionStatus();
+        result[0] = mImsSsInfo.get(0).getStatus();
+        result[1] = mImsSsInfo.get(0).getProvisionStatus();
         return result;
     }
 
     /**
      * @return an array of {@link ImsSsInfo}s associated with this supplementary service data.
      */
-    public @NonNull ImsSsInfo[] getSuppServiceInfo() {
+    public @NonNull List<ImsSsInfo> getSuppServiceInfo() {
         return mImsSsInfo;
     }
 
@@ -562,7 +566,7 @@
      * @return an array of {@link ImsCallForwardInfo}s associated with this supplementary service
      * data.
      **/
-    public ImsCallForwardInfo[] getCallForwardInfo() {
+    public @Nullable List<ImsCallForwardInfo> getCallForwardInfo() {
         return mCfInfo;
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 303a9fe..18e7530 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -173,7 +173,7 @@
     /**
      * Builds {@link ImsSsInfo} instances, which may include optional parameters.
      */
-    public static class Builder {
+    public static final class Builder {
 
         private final ImsSsInfo mImsSsInfo;
 
@@ -304,7 +304,7 @@
     /**
      * @return The Incoming Communication Barring (ICB) number.
      */
-    public String getIncomingCommunicationBarringNumber() {
+    public @Nullable String getIncomingCommunicationBarringNumber() {
         return mIcbNum;
     }
 
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 6e98a0a..9104d9f 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.WorkerThread;
@@ -177,7 +178,7 @@
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
      * @throws IllegalArgumentException if the subscription is invalid.
      */
-    public static ProvisioningManager createForSubscriptionId(int subId) {
+    public static @NonNull ProvisioningManager createForSubscriptionId(int subId) {
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             throw new IllegalArgumentException("Invalid subscription ID");
         }
@@ -206,7 +207,7 @@
      * reason.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
+    public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull Callback callback) throws ImsException {
         callback.setExecutor(executor);
         try {
@@ -271,7 +272,7 @@
      */
     @WorkerThread
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public String getProvisioningStringValue(int key) {
+    public @Nullable String getProvisioningStringValue(int key) {
         try {
             return getITelephony().getImsProvisioningString(mSubId, key);
         } catch (RemoteException e) {
@@ -313,7 +314,7 @@
     @WorkerThread
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
-            String value) {
+            @NonNull String value) {
         try {
             return getITelephony().setImsProvisioningString(mSubId, key, value);
         } catch (RemoteException e) {
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 0e3d12b..0364477 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -18,6 +18,8 @@
 
 import android.telephony.AvailableNetworkInfo;
 
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
+
 interface IOns {
 
     /**
@@ -62,11 +64,13 @@
      * @param subId which opportunistic subscription
      * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
      * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @param needValidation whether validation is needed before switch happens.
+     * @param callback callback upon request completion.
      * @param callingPackage caller's package name
-     * @return true if request is accepted, else false.
      *
      */
-    boolean setPreferredDataSubscriptionId(int subId, String callingPackage);
+    void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+            ISetOpportunisticDataCallback callbackStub, String callingPackage);
 
     /**
      * Get preferred opportunistic data subscription Id
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index e87d28c..d5061a3 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -141,6 +141,8 @@
     /** APN type for Emergency PDN. This is not an IA apn, but is used
      * for access to carrier services in an emergency call situation. */
     public static final String APN_TYPE_EMERGENCY = "emergency";
+    /** APN type for Mission Critical Services */
+    public static final String APN_TYPE_MCX = "mcx";
     /** Array of all APN types */
     public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
             APN_TYPE_MMS,
@@ -151,7 +153,8 @@
             APN_TYPE_IMS,
             APN_TYPE_CBS,
             APN_TYPE_IA,
-            APN_TYPE_EMERGENCY
+            APN_TYPE_EMERGENCY,
+            APN_TYPE_MCX
     };
 
     public static final int RIL_CARD_MAX_APPS    = 8;
diff --git a/tests/ActivityManagerPerfTests/tests/Android.mk b/tests/ActivityManagerPerfTests/tests/Android.mk
index f23a665..e1f56b8 100644
--- a/tests/ActivityManagerPerfTests/tests/Android.mk
+++ b/tests/ActivityManagerPerfTests/tests/Android.mk
@@ -21,7 +21,7 @@
     $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     apct-perftests-utils \
     ActivityManagerPerfTestsUtils
 
diff --git a/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
index a1ab33a..04aef47 100644
--- a/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
+++ b/tests/ActivityManagerPerfTests/tests/AndroidManifest.xml
@@ -25,6 +25,6 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.frameworks.perftests.amtests"/>
 </manifest>
diff --git a/tests/ActivityManagerPerfTests/tests/AndroidTest.xml b/tests/ActivityManagerPerfTests/tests/AndroidTest.xml
index ffb5404..76c40b2 100644
--- a/tests/ActivityManagerPerfTests/tests/AndroidTest.xml
+++ b/tests/ActivityManagerPerfTests/tests/AndroidTest.xml
@@ -24,6 +24,6 @@
     <option name="test-tag" value="ActivityManagerPerfTests"/>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.frameworks.perftests.amtests"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
     </test>
 </configuration>
\ No newline at end of file
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
index 58fb136..daff76f 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BasePerfTest.java
@@ -21,7 +21,8 @@
 import android.content.ServiceConnection;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.PerfManualStatusReporter;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import com.android.frameworks.perftests.am.util.TargetPackageUtils;
 import com.android.frameworks.perftests.am.util.TimeReceiver;
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
index f7dab03..bc528d4 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/BroadcastPerfTest.java
@@ -17,8 +17,9 @@
 package com.android.frameworks.perftests.am.tests;
 
 import android.content.Intent;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.perftests.am.util.Constants;
 
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ContentProviderPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ContentProviderPerfTest.java
index 3bf56ce..8e82219 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ContentProviderPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ContentProviderPerfTest.java
@@ -17,8 +17,9 @@
 package com.android.frameworks.perftests.am.tests;
 
 import android.content.ContentProviderClient;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.perftests.am.util.TargetPackageUtils;
 
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java
index e1263db..996c5a5 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceBindPerfTest.java
@@ -21,8 +21,9 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.perftests.am.util.Constants;
 import com.android.frameworks.perftests.am.util.TargetPackageUtils;
diff --git a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java
index f05f323..ba20640 100644
--- a/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java
+++ b/tests/ActivityManagerPerfTests/tests/src/com/android/frameworks/perftests/am/tests/ServiceStartPerfTest.java
@@ -19,8 +19,9 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.perftests.am.util.Constants;
 import com.android.frameworks.perftests.am.util.TargetPackageUtils;
diff --git a/tests/ActivityManagerPerfTests/utils/Android.mk b/tests/ActivityManagerPerfTests/utils/Android.mk
index 60c9423..7a7471d 100644
--- a/tests/ActivityManagerPerfTests/utils/Android.mk
+++ b/tests/ActivityManagerPerfTests/utils/Android.mk
@@ -23,7 +23,7 @@
     src/com/android/frameworks/perftests/am/util/ITimeReceiverCallback.aidl
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     junit \
     ub-uiautomator
 
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
index 67071d2..fc787ba 100644
--- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
@@ -19,10 +19,11 @@
 import android.content.Intent;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.io.IOException;
 
 public class Utils {
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
index 1fb548b..f50bca5 100644
--- a/tests/AppLaunch/Android.mk
+++ b/tests/AppLaunch/Android.mk
@@ -12,7 +12,7 @@
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
 
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 5ea8ff1..9d7319f 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -30,11 +30,12 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.rule.logging.AtraceLogger;
 import android.test.InstrumentationTestCase;
 import android.test.InstrumentationTestRunner;
 import android.util.Log;
 
+import androidx.test.rule.logging.AtraceLogger;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -51,6 +52,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 /**
  * This test is intended to measure the time it takes for the apps to start.
  * Names of the applications are passed in command line, and the
diff --git a/tests/AppLaunchWear/Android.mk b/tests/AppLaunchWear/Android.mk
index 6d08366..332b680 100644
--- a/tests/AppLaunchWear/Android.mk
+++ b/tests/AppLaunchWear/Android.mk
@@ -12,7 +12,7 @@
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
 
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
diff --git a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
index d36d84e..97701c6 100644
--- a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
@@ -30,16 +30,16 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.rule.logging.AtraceLogger;
 import android.test.InstrumentationTestCase;
 import android.test.InstrumentationTestRunner;
 import android.util.Log;
 
+import androidx.test.rule.logging.AtraceLogger;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -52,6 +52,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 /**
  * This test is intended to measure the time it takes for the apps to start.
  * Names of the applications are passed in command line, and the
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/Android.mk b/tests/BackgroundDexOptServiceIntegrationTests/Android.mk
index b10305d..f47cf96 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/Android.mk
+++ b/tests/BackgroundDexOptServiceIntegrationTests/Android.mk
@@ -24,7 +24,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
 
 LOCAL_PACKAGE_NAME := BackgroundDexOptServiceIntegrationTests
 LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
index afae155..aec9f77 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
+++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidManifest.xml
@@ -34,7 +34,7 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.frameworks.bgdexopttest"
         android:label="Integration test for BackgroundDexOptService" />
 </manifest>
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml b/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml
index 9bb1e28..a532422 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml
+++ b/tests/BackgroundDexOptServiceIntegrationTests/AndroidTest.xml
@@ -50,6 +50,6 @@
     <option name="test-tag" value="BackgroundDexOptServiceIntegrationTests"/>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.frameworks.bgdexopttest"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
     </test>
 </configuration>
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index fd20f4a..7d826f7 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -17,17 +17,16 @@
 package com.android.server.pm;
 
 import android.app.AlarmManager;
-import android.app.UiAutomation;
 import android.content.Context;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemProperties;
 import android.os.storage.StorageManager;
-import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
diff --git a/tests/Camera2Tests/CameraToo/tests/Android.mk b/tests/Camera2Tests/CameraToo/tests/Android.mk
index eb8f6c3..fe4dc42 100644
--- a/tests/Camera2Tests/CameraToo/tests/Android.mk
+++ b/tests/Camera2Tests/CameraToo/tests/Android.mk
@@ -20,6 +20,6 @@
 LOCAL_INSTRUMENTATION_FOR := CameraToo
 LOCAL_SDK_VERSION := current
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test mockito-target-minus-junit4
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules mockito-target-minus-junit4
 
 include $(BUILD_PACKAGE)
diff --git a/tests/Camera2Tests/CameraToo/tests/AndroidManifest.xml b/tests/Camera2Tests/CameraToo/tests/AndroidManifest.xml
index 30210ba..8d35749 100644
--- a/tests/Camera2Tests/CameraToo/tests/AndroidManifest.xml
+++ b/tests/Camera2Tests/CameraToo/tests/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <application android:label="CameraToo">
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.example.android.camera2.cameratoo"
         android:label="CameraToo tests" />
 </manifest>
diff --git a/tests/Compatibility/Android.mk b/tests/Compatibility/Android.mk
index 9c47a26..643f9eb 100644
--- a/tests/Compatibility/Android.mk
+++ b/tests/Compatibility/Android.mk
@@ -17,7 +17,7 @@
 
 # We only want this apk build for tests.
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
 # Include all test java files.
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, src)
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
index 95eb5c9..d683ec7 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -33,10 +33,11 @@
 import android.os.DropBoxManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
index b61ec34..960ea49 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibilityRunner.java
@@ -16,7 +16,7 @@
 
 package com.android.compatibilitytest;
 
-import android.support.test.runner.AndroidJUnitRunner;
+import androidx.test.runner.AndroidJUnitRunner;
 
 // empty subclass to maintain backwards compatibility on host-side harness
 public class AppCompatibilityRunner extends AndroidJUnitRunner {}
diff --git a/tests/DynamicCodeLoggerIntegrationTests/Android.mk b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
index f324eb1..62c1ba8 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/Android.mk
+++ b/tests/DynamicCodeLoggerIntegrationTests/Android.mk
@@ -67,7 +67,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/server/pm)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     truth-prebuilt \
 
 # Include both versions of the .so if we have 2 arch
diff --git a/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml b/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
index 4327da2..08fac30 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
+++ b/tests/DynamicCodeLoggerIntegrationTests/AndroidManifest.xml
@@ -29,7 +29,7 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.frameworks.dynamiccodeloggertest"
         android:label="Integration test for DynamicCodeLogger" />
 </manifest>
diff --git a/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
index f70b9c8..f8a1ec9 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
+++ b/tests/DynamicCodeLoggerIntegrationTests/AndroidTest.xml
@@ -24,7 +24,7 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.frameworks.dynamiccodeloggertest"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 4f9aeea..db2f659 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -24,11 +24,12 @@
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
 import android.util.EventLog;
 import android.util.EventLog.Event;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
 import dalvik.system.DexClassLoader;
 
 import org.junit.Before;
diff --git a/tests/FlickerTests/AndroidManifest.xml b/tests/FlickerTests/AndroidManifest.xml
index ba63940..5b1a36b 100644
--- a/tests/FlickerTests/AndroidManifest.xml
+++ b/tests/FlickerTests/AndroidManifest.xml
@@ -29,7 +29,7 @@
         <uses-library android:name="android.test.runner"/>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.server.wm.flicker"
                      android:label="WindowManager Flicker Tests">
     </instrumentation>
diff --git a/tests/FlickerTests/lib/Android.mk b/tests/FlickerTests/lib/Android.mk
index 6a8dfe8..e438822 100644
--- a/tests/FlickerTests/lib/Android.mk
+++ b/tests/FlickerTests/lib/Android.mk
@@ -24,7 +24,7 @@
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_STATIC_JAVA_LIBRARIES := \
-   ub-janktesthelper \
+   androidx.test.janktesthelper \
    cts-amwm-util \
    platformprotosnano \
    layersprotosnano \
@@ -41,7 +41,7 @@
     src/com/android/server/wm/flicker/WindowUtils.java
 LOCAL_STATIC_JAVA_LIBRARIES := sysui-helper \
     launcher-helper-lib \
-    compatibility-device-util
+    compatibility-device-util-axt
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
index 6306f0e..e00a247 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/AutomationUtils.java
@@ -30,7 +30,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.launcherhelper.LauncherStrategyFactory;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
@@ -43,6 +42,8 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 
+import androidx.test.InstrumentationRegistry;
+
 /**
  * Collection of UI Automation helper functions.
  */
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
index f6e8192..0a3fe3c 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/TransitionRunner.java
@@ -18,9 +18,10 @@
 
 import android.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
-import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.wm.flicker.monitor.ITransitionMonitor;
 import com.android.server.wm.flicker.monitor.LayersTraceMonitor;
 import com.android.server.wm.flicker.monitor.ScreenRecorder;
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
index 0da8761..c54396f 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/WindowUtils.java
@@ -20,10 +20,11 @@
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
 import android.view.Surface;
 import android.view.WindowManager;
 
+import androidx.test.InstrumentationRegistry;
+
 /**
  * Helper functions to retrieve system window sizes and positions.
  */
diff --git a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java
index 717d187..3f86f0d 100644
--- a/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java
+++ b/tests/FlickerTests/lib/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitor.java
@@ -25,7 +25,7 @@
 /**
  * Monitors {@link android.view.WindowAnimationFrameStats} to detect janky frames.
  *
- * Adapted from {@link android.support.test.jank.internal.WindowAnimationFrameStatsMonitorImpl}
+ * Adapted from {@link androidx.test.jank.internal.WindowAnimationFrameStatsMonitorImpl}
  * using the same threshold to determine jank.
  */
 public class WindowAnimationFrameStatsMonitor implements ITransitionMonitor {
diff --git a/tests/FlickerTests/lib/test/Android.mk b/tests/FlickerTests/lib/test/Android.mk
index 0e3f58d..5be89ba 100644
--- a/tests/FlickerTests/lib/test/Android.mk
+++ b/tests/FlickerTests/lib/test/Android.mk
@@ -25,7 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     platform-test-annotations \
     truth-prebuilt \
     platformprotosnano \
diff --git a/tests/FlickerTests/lib/test/AndroidManifest.xml b/tests/FlickerTests/lib/test/AndroidManifest.xml
index d30172d..6451a57 100644
--- a/tests/FlickerTests/lib/test/AndroidManifest.xml
+++ b/tests/FlickerTests/lib/test/AndroidManifest.xml
@@ -18,7 +18,7 @@
         <uses-library android:name="android.test.runner"/>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.server.wm.flicker"
                      android:label="WindowManager Flicker Lib Test">
     </instrumentation>
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java
index 42b2aca..7d77126 100644
--- a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/LayersTraceTest.java
@@ -26,9 +26,10 @@
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
 import android.view.WindowManager;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.Test;
 
 import java.util.List;
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java
index 5a24e6d..c46175c 100644
--- a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/TestFileUtils.java
@@ -17,7 +17,8 @@
 package com.android.server.wm.flicker;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import com.google.common.io.ByteStreams;
 
diff --git a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
index f7fa0d5..dd6fed0 100644
--- a/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
+++ b/tests/FlickerTests/lib/test/src/com/android/server/wm/flicker/monitor/WindowAnimationFrameStatsMonitorTest.java
@@ -18,9 +18,7 @@
 
 import static com.android.server.wm.flicker.AutomationUtils.wakeUpAndGoToHomeScreen;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import android.support.test.InstrumentationRegistry;
+import androidx.test.InstrumentationRegistry;
 
 import org.junit.Before;
 import org.junit.Ignore;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
index 34f4ebb..b6860cb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
@@ -25,11 +25,12 @@
 import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
 
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
 import android.util.Log;
 import android.view.Surface;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java
index 2b62fcf..6590b86 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToAppTest.java
@@ -20,9 +20,10 @@
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
index 42b161f..4771b02 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
@@ -20,9 +20,10 @@
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
index 92bb1ea..65888ac 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.java
@@ -30,7 +30,6 @@
 import android.content.Intent;
 import android.os.RemoteException;
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
@@ -38,6 +37,8 @@
 import android.util.Rational;
 import android.view.Surface;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
 
 /**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java
index fec248c..61cca0d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.java
@@ -17,12 +17,13 @@
 package com.android.server.wm.flicker;
 
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.util.Rational;
 import android.view.Surface;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
index 7061b23..00e11c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.java
@@ -21,10 +21,11 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
 
 import org.junit.After;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java
index 7e71369..7818c4e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppColdTest.java
@@ -20,9 +20,9 @@
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java
index 745569a..63018ec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppToSplitScreenTest.java
@@ -19,9 +19,9 @@
 import static com.android.server.wm.flicker.CommonTransitions.appToSplitScreen;
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java
index de7639d..1aba930 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenAppWarmTest.java
@@ -20,9 +20,9 @@
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java
index 1bd519c..a81fa8e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/OpenImeWindowTest.java
@@ -19,8 +19,8 @@
 import static com.android.server.wm.flicker.CommonTransitions.editTextSetFocus;
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java
index 8a15cbd..50dba81 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ResizeSplitScreenTest.java
@@ -25,11 +25,12 @@
 
 import android.graphics.Rect;
 import android.platform.helpers.IAppHelper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Rational;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
index 3eab68d..117ac5a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
@@ -27,10 +27,11 @@
 
 import android.content.Intent;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
 import android.view.Surface;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java
index 40bd4e9..1d30df9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SplitScreenToLauncherTest.java
@@ -19,10 +19,10 @@
 import static com.android.server.wm.flicker.CommonTransitions.splitScreenToLauncher;
 import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/Internal/Android.mk b/tests/Internal/Android.mk
index da56696..2e26ef1 100644
--- a/tests/Internal/Android.mk
+++ b/tests/Internal/Android.mk
@@ -11,7 +11,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit \
-    android-support-test \
+    androidx.test.rules \
     mockito-target-minus-junit4
 
 LOCAL_JAVA_RESOURCE_DIRS := res
diff --git a/tests/Internal/AndroidManifest.xml b/tests/Internal/AndroidManifest.xml
index e5a5694..c85c3b1 100644
--- a/tests/Internal/AndroidManifest.xml
+++ b/tests/Internal/AndroidManifest.xml
@@ -38,7 +38,7 @@
         </service>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.internal.tests"
                      android:label="Internal Tests" />
 </manifest>
diff --git a/tests/Internal/AndroidTest.xml b/tests/Internal/AndroidTest.xml
index 6531c93..7b67e9e 100644
--- a/tests/Internal/AndroidTest.xml
+++ b/tests/Internal/AndroidTest.xml
@@ -24,6 +24,6 @@
     <option name="test-tag" value="InternalTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.internal.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
\ No newline at end of file
diff --git a/tests/Internal/src/android/app/WallpaperColorsTest.java b/tests/Internal/src/android/app/WallpaperColorsTest.java
index 881f628..65ff6eb 100644
--- a/tests/Internal/src/android/app/WallpaperColorsTest.java
+++ b/tests/Internal/src/android/app/WallpaperColorsTest.java
@@ -20,8 +20,9 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Assert;
 import org.junit.Test;
diff --git a/tests/Internal/src/android/app/WallpaperInfoTest.java b/tests/Internal/src/android/app/WallpaperInfoTest.java
index 7f06f2c..476b991 100644
--- a/tests/Internal/src/android/app/WallpaperInfoTest.java
+++ b/tests/Internal/src/android/app/WallpaperInfoTest.java
@@ -26,9 +26,10 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.service.wallpaper.WallpaperService;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
index b9e282e..592aa3a 100644
--- a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
+++ b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
@@ -20,7 +20,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
index 39608a4..17fa931 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
@@ -27,9 +27,10 @@
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.graphics.Color;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.colorextraction.types.ExtractionType;
diff --git a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
index a7d5ae8..d92cfce 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
@@ -20,11 +20,12 @@
 
 import android.app.WallpaperColors;
 import android.graphics.Color;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Range;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.graphics.ColorUtils;
 
diff --git a/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java b/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
index 73df9a0..d0bb8e3 100644
--- a/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
+++ b/tests/Internal/src/com/android/internal/graphics/ColorUtilsTest.java
@@ -16,13 +16,14 @@
 
 package com.android.internal.graphics;
 
+import static org.junit.Assert.assertTrue;
+
 import android.graphics.Color;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
-import static org.junit.Assert.assertTrue;
-
 @SmallTest
 public class ColorUtilsTest {
 
diff --git a/tests/Internal/src/com/android/internal/ml/clustering/KMeansTest.java b/tests/Internal/src/com/android/internal/ml/clustering/KMeansTest.java
index a64f8a6..540a1ec 100644
--- a/tests/Internal/src/com/android/internal/ml/clustering/KMeansTest.java
+++ b/tests/Internal/src/com/android/internal/ml/clustering/KMeansTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.annotation.SuppressLint;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/tests/PackageWatchdog/Android.mk b/tests/PackageWatchdog/Android.mk
index 1c1c2a4..1e4aacc 100644
--- a/tests/PackageWatchdog/Android.mk
+++ b/tests/PackageWatchdog/Android.mk
@@ -22,7 +22,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     junit \
     frameworks-base-testutils \
-    android-support-test \
+    androidx.test.rules \
     services.core
 
 LOCAL_JAVA_LIBRARIES := \
diff --git a/tests/PackageWatchdog/AndroidManifest.xml b/tests/PackageWatchdog/AndroidManifest.xml
index fa89528..540edb4 100644
--- a/tests/PackageWatchdog/AndroidManifest.xml
+++ b/tests/PackageWatchdog/AndroidManifest.xml
@@ -22,7 +22,7 @@
     </application>
 
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.tests.packagewatchdog"
                      android:label="PackageWatchdog Test"/>
 </manifest>
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 77cd62e..d0c2612 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -24,7 +24,8 @@
 
 import android.content.pm.VersionedPackage;
 import android.os.test.TestLooper;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import com.android.server.PackageWatchdog.PackageHealthObserver;
 import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
@@ -76,11 +77,12 @@
         TestObserver observer3 = new TestObserver(OBSERVER_NAME_3);
 
         // Start observing for observer1 which will be unregistered
-        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
         // Start observing for observer2 which will expire
-        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
+        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION,
+                false);
         // Start observing for observer3 which will have expiry duration reduced
-        watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), LONG_DURATION, false);
 
         // Verify packages observed at start
         // 1
@@ -143,8 +145,9 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog1.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog1.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
+        watchdog1.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
+        watchdog1.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION,
+                false);
 
         // Verify 2 observers are registered and saved internally
         // 1
@@ -190,8 +193,8 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
+        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
 
         // Then fail APP_A below the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) {
@@ -217,8 +220,8 @@
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
 
-        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.startObservingHealth(observer1, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
+        watchdog.startObservingHealth(observer1, Arrays.asList(APP_B), SHORT_DURATION, false);
 
         // Then fail APP_C (not observed) above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
@@ -252,7 +255,7 @@
                 }
             };
 
-        watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION, false);
 
         // Then fail APP_A (different version) above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
@@ -285,13 +288,13 @@
 
         // Start observing for all impact observers
         watchdog.startObservingHealth(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D),
-                SHORT_DURATION);
+                SHORT_DURATION, false);
         watchdog.startObservingHealth(observerHigh, Arrays.asList(APP_A, APP_B, APP_C),
-                SHORT_DURATION);
+                SHORT_DURATION, false);
         watchdog.startObservingHealth(observerMid, Arrays.asList(APP_A, APP_B),
-                SHORT_DURATION);
+                SHORT_DURATION, false);
         watchdog.startObservingHealth(observerLow, Arrays.asList(APP_A),
-                SHORT_DURATION);
+                SHORT_DURATION, false);
 
         // Then fail all apps above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
@@ -343,8 +346,8 @@
                 PackageHealthObserverImpact.USER_IMPACT_MEDIUM);
 
         // Start observing for observerFirst and observerSecond with failure handling
-        watchdog.startObservingHealth(observerFirst, Arrays.asList(APP_A), LONG_DURATION);
-        watchdog.startObservingHealth(observerSecond, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.startObservingHealth(observerFirst, Arrays.asList(APP_A), LONG_DURATION, false);
+        watchdog.startObservingHealth(observerSecond, Arrays.asList(APP_A), LONG_DURATION, false);
 
         // Then fail APP_A above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
@@ -421,8 +424,8 @@
                 PackageHealthObserverImpact.USER_IMPACT_HIGH);
 
         // Start observing for observer1 and observer2 with failure handling
-        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION, false);
+        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, false);
 
         // Then fail APP_A above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
@@ -438,6 +441,49 @@
         assertEquals(0, observer2.mFailedPackages.size());
     }
 
+    /**
+     * Test explicit health check status determines package failure or success on expiry
+     */
+    @Test
+    public void testPackageFailureExplicitHealthCheck() throws Exception {
+        PackageWatchdog watchdog = createWatchdog();
+        TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
+                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+        TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
+                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+        TestObserver observer3 = new TestObserver(OBSERVER_NAME_3,
+                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+
+
+        // Start observing with explicit health checks for APP_A and APP_B respectively
+        // with observer1 and observer2
+        watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION, true);
+        watchdog.startObservingHealth(observer2, Arrays.asList(APP_B), SHORT_DURATION, true);
+        // Explicit health check passed for APP_A (observer1 is aware)
+        watchdog.onExplicitHealthCheckPassed(APP_A);
+        // Start observing APP_A with explicit health checks for observer3.
+        // Observer3 didn't exist when we got the explicit health check above, so
+        // it starts out with a non-passing explicit health check and has to wait for a pass
+        // otherwise it would be notified of APP_A failure on expiry
+        watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), SHORT_DURATION, true);
+
+        // Then expire observers
+        Thread.sleep(SHORT_DURATION);
+        // Run handler so package failures are dispatched to observers
+        mTestLooper.dispatchAll();
+
+        // Verify observer1 is not notified
+        assertEquals(0, observer1.mFailedPackages.size());
+
+        // Verify observer2 is notifed because health checks for APP_B never passed
+        assertEquals(1, observer2.mFailedPackages.size());
+        assertEquals(APP_B, observer2.mFailedPackages.get(0));
+
+        // Verify observer3 is notifed because health checks for APP_A did not pass before expiry
+        assertEquals(1, observer3.mFailedPackages.size());
+        assertEquals(APP_A, observer3.mFailedPackages.get(0));
+    }
+
     private PackageWatchdog createWatchdog() {
         return new PackageWatchdog(InstrumentationRegistry.getContext(),
                 mTestLooper.getLooper());
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
index 7b348d7..a276584 100644
--- a/tests/RcsTests/Android.mk
+++ b/tests/RcsTests/Android.mk
@@ -11,7 +11,7 @@
 
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4 truth-prebuilt
+LOCAL_STATIC_JAVA_LIBRARIES := junit androidx.test.rules mockito-target-minus-junit4 truth-prebuilt
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
index a7e7d47..b1706a0 100644
--- a/tests/RcsTests/AndroidManifest.xml
+++ b/tests/RcsTests/AndroidManifest.xml
@@ -6,6 +6,6 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.tests.rcs"/>
 </manifest>
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index 89d32ab..e898942 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -19,10 +19,11 @@
 
 import android.net.Uri;
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsGroupThreadIconChangedEvent;
 import android.telephony.ims.RcsGroupThreadIconChangedEventDescriptor;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 726b9cd..356688d 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsGroupThreadNameChangedEvent;
 import android.telephony.ims.RcsGroupThreadNameChangedEventDescriptor;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index a109310..572fcb8 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsGroupThreadParticipantJoinedEvent;
 import android.telephony.ims.RcsGroupThreadParticipantJoinedEventDescriptor;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index de2688c..038b2e8 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsGroupThreadParticipantLeftEvent;
 import android.telephony.ims.RcsGroupThreadParticipantLeftEventDescriptor;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 5724054..283c71b 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -18,10 +18,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsParticipantAliasChangedEvent;
 import android.telephony.ims.RcsParticipantAliasChangedEventDescriptor;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
index 6361a39..2d95513 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
@@ -18,9 +18,10 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsParticipantQueryParams;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
index beb4f8a..fb51bda 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -21,10 +21,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.ims.RcsParticipant;
 import android.telephony.ims.RcsThreadQueryParams;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk
index db9376b..206f867 100644
--- a/tests/RollbackTest/Android.mk
+++ b/tests/RollbackTest/Android.mk
@@ -107,7 +107,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, RollbackTest/src)
 LOCAL_PACKAGE_NAME := RollbackTest
 LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
 LOCAL_COMPATIBILITY_SUITE := general-tests
 LOCAL_JAVA_RESOURCE_FILES := \
   $(ROLLBACK_TEST_APP_AV1) \
diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml
index ac39f85..70cd867 100644
--- a/tests/RollbackTest/RollbackTest.xml
+++ b/tests/RollbackTest/RollbackTest.xml
@@ -20,7 +20,7 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.tests.rollback" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
 
         <!-- Exclude the StagedRollbackTest tests, which needs to be specially
              driven from the StagedRollbackTest host test -->
diff --git a/tests/RollbackTest/RollbackTest/AndroidManifest.xml b/tests/RollbackTest/RollbackTest/AndroidManifest.xml
index e57a768..5380dc9 100644
--- a/tests/RollbackTest/RollbackTest/AndroidManifest.xml
+++ b/tests/RollbackTest/RollbackTest/AndroidManifest.xml
@@ -24,7 +24,7 @@
     </application>
 
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.tests.rollback"
                      android:label="Rollback Test"/>
 
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
index ddcf1da..267ef73 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
@@ -21,7 +21,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.InstrumentationRegistry;
 
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
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 e10f866..8a925b9 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
@@ -20,9 +20,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
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 a6054e8..7e183db 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -21,6 +21,11 @@
 import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
 import static com.android.tests.rollback.RollbackTestUtils.processUserData;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
 import android.Manifest;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
@@ -31,13 +36,9 @@
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
 import android.provider.DeviceConfig;
-import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import androidx.test.InstrumentationRegistry;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -378,6 +379,83 @@
             // Check that the data has expired after the expiration time (with a buffer of 1 second)
             Thread.sleep(expirationTime / 2);
             assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
+
+        } finally {
+            DeviceConfig.setProperty(DeviceConfig.Rollback.BOOT_NAMESPACE,
+                    DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
+                    Long.toString(defaultExpirationTime), false /* makeDefault*/);
+            RollbackTestUtils.dropShellPermissionIdentity();
+        }
+    }
+
+    /**
+     * Test that changing time on device does not affect the duration of time that we keep
+     * rollback available
+     */
+    @Test
+    public void testTimeChangeDoesNotAffectLifetime() throws Exception {
+        long expirationTime = TimeUnit.SECONDS.toMillis(30);
+        long defaultExpirationTime = TimeUnit.HOURS.toMillis(48);
+        RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+        try {
+            RollbackTestUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.WRITE_DEVICE_CONFIG,
+                    Manifest.permission.SET_TIME);
+
+            DeviceConfig.setProperty(DeviceConfig.Rollback.BOOT_NAMESPACE,
+                    DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
+                    Long.toString(expirationTime), false /* makeDefault*/);
+
+            // Pull the new expiration time from DeviceConfig
+            rm.reloadPersistedData();
+
+            // Install app A with rollback enabled
+            RollbackTestUtils.uninstall(TEST_APP_A);
+            RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+            RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            Thread.sleep(expirationTime / 2);
+
+            // Install app B with rollback enabled
+            RollbackTestUtils.uninstall(TEST_APP_B);
+            RollbackTestUtils.install("RollbackTestAppBv1.apk", false);
+            RollbackTestUtils.install("RollbackTestAppBv2.apk", true);
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
+            // 1 second buffer
+            Thread.sleep(1000);
+
+            try {
+                // Change the time
+                RollbackTestUtils.forwardTimeBy(expirationTime);
+
+                // 1 second buffer to allow Rollback Manager to handle time change before loading
+                // persisted data
+                Thread.sleep(1000);
+
+                // Load timestamps from storage
+                rm.reloadPersistedData();
+
+                // Wait until rollback for app A has expired
+                // This will trigger an expiration run that should expire app A but not B
+                Thread.sleep(expirationTime / 2);
+                assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
+
+                // Rollback for app B should not be expired
+                RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                        rm.getAvailableRollbacks(), TEST_APP_B);
+                assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollback);
+
+                // Wait until rollback for app B has expired
+                Thread.sleep(expirationTime / 2);
+                assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B));
+            } finally {
+                RollbackTestUtils.forwardTimeBy(-expirationTime);
+            }
         } finally {
             DeviceConfig.setProperty(DeviceConfig.Rollback.BOOT_NAMESPACE,
                     DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS,
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 2f989f3..ed8a533 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -16,6 +16,12 @@
 
 package com.android.tests.rollback;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -30,13 +36,9 @@
 import android.content.rollback.RollbackManager;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.support.test.InstrumentationRegistry;
 import android.util.Log;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import androidx.test.InstrumentationRegistry;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -62,6 +64,17 @@
         return rm;
     }
 
+    private static void setTime(long millis) {
+        Context context = InstrumentationRegistry.getContext();
+        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        am.setTime(millis);
+    }
+
+    static void forwardTimeBy(long offsetMillis) {
+        setTime(System.currentTimeMillis() + offsetMillis);
+        Log.i(TAG, "Forwarded time on device by " + offsetMillis + " millis");
+    }
+
     /**
      * Returns the version of the given package installed on device.
      * Returns -1 if the package is not currently installed.
diff --git a/tests/ServiceCrashTest/Android.mk b/tests/ServiceCrashTest/Android.mk
index d1f6450..617ee7c 100644
--- a/tests/ServiceCrashTest/Android.mk
+++ b/tests/ServiceCrashTest/Android.mk
@@ -12,7 +12,7 @@
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := android.test.base
 
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt androidx.test.rules
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/UsageStatsPerfTests/Android.mk b/tests/UsageStatsPerfTests/Android.mk
index cd29b51..4304fb0 100644
--- a/tests/UsageStatsPerfTests/Android.mk
+++ b/tests/UsageStatsPerfTests/Android.mk
@@ -21,7 +21,7 @@
     $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-test \
+    androidx.test.rules \
     apct-perftests-utils \
     services.usage
 
diff --git a/tests/UsageStatsPerfTests/AndroidManifest.xml b/tests/UsageStatsPerfTests/AndroidManifest.xml
index 596a79c..9891548 100644
--- a/tests/UsageStatsPerfTests/AndroidManifest.xml
+++ b/tests/UsageStatsPerfTests/AndroidManifest.xml
@@ -24,6 +24,6 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.frameworks.perftests.usage"/>
 </manifest>
diff --git a/tests/UsageStatsPerfTests/AndroidTest.xml b/tests/UsageStatsPerfTests/AndroidTest.xml
index c9b51dc..b8892eb 100644
--- a/tests/UsageStatsPerfTests/AndroidTest.xml
+++ b/tests/UsageStatsPerfTests/AndroidTest.xml
@@ -23,6 +23,6 @@
     <option name="test-tag" value="UsageStatsPerfTests"/>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.frameworks.perftests.usage"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
     </test>
 </configuration>
\ No newline at end of file
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index e2a4c26..7d9d0d5 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -24,9 +24,10 @@
 import android.os.SystemClock;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.PerfManualStatusReporter;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.usage.IntervalStats;
 import com.android.server.usage.UsageStatsDatabase;
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index 0105893..adcd11a 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -41,6 +41,7 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -196,8 +197,8 @@
                     intent.setPackage(getPackageName());
                     intent.putExtra(EXTRA_KEY_TIMEOUT, true);
                     mUsageStatsManager.registerAppUsageLimitObserver(1, packages,
-                            60, TimeUnit.SECONDS, PendingIntent.getActivity(UsageStatsActivity.this,
-                                    1, intent, 0));
+                            Duration.ofSeconds(60), Duration.ofSeconds(60),
+                            PendingIntent.getActivity(UsageStatsActivity.this, 1, intent, 0));
                 }
             }
         });
diff --git a/tests/UsbTests/Android.mk b/tests/UsbTests/Android.mk
index 4e215cc..aef993b 100644
--- a/tests/UsbTests/Android.mk
+++ b/tests/UsbTests/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     frameworks-base-testutils \
-    android-support-test \
+    androidx.test.rules \
     mockito-target-inline-minus-junit4 \
     platform-test-annotations \
     services.core \
diff --git a/tests/UsbTests/AndroidManifest.xml b/tests/UsbTests/AndroidManifest.xml
index 5d60695..03d1a3e 100644
--- a/tests/UsbTests/AndroidManifest.xml
+++ b/tests/UsbTests/AndroidManifest.xml
@@ -24,7 +24,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.server.usb"
                      android:label="UsbTests"/>
 </manifest>
diff --git a/tests/UsbTests/AndroidTest.xml b/tests/UsbTests/AndroidTest.xml
index 4affad3..e55bc98 100644
--- a/tests/UsbTests/AndroidTest.xml
+++ b/tests/UsbTests/AndroidTest.xml
@@ -24,7 +24,7 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.server.usb"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbDescriptorParserTests.java b/tests/UsbTests/src/com/android/server/usb/UsbDescriptorParserTests.java
index ea027d7..89dc79c 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbDescriptorParserTests.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbDescriptorParserTests.java
@@ -16,29 +16,29 @@
 
 package com.android.server.usb;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.usb.descriptors.UsbDescriptorParser;
-import com.android.server.usb.descriptors.UsbDeviceDescriptor;
-import com.google.common.io.ByteStreams;
 
-import java.io.InputStream;
-import java.io.IOException;
-import java.lang.Exception;
+import com.google.common.io.ByteStreams;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.IOException;
+import java.io.InputStream;
+
 /**
  * Tests for {@link com.android.server.usb.descriptors.UsbDescriptorParser}
  */
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
index 4b93ca3..ca1eb70 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbHandlerTest.java
@@ -31,11 +31,11 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.FgThread;
 
diff --git a/tests/WindowAnimationJank/Android.mk b/tests/WindowAnimationJank/Android.mk
index 7800a80..1c2d167 100644
--- a/tests/WindowAnimationJank/Android.mk
+++ b/tests/WindowAnimationJank/Android.mk
@@ -26,7 +26,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     ub-uiautomator \
-    ub-janktesthelper \
+    androidx.test.janktesthelper \
     junit
 
 LOCAL_JAVA_LIBRARIES := android.test.base.stubs
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/FullscreenRotationTest.java b/tests/WindowAnimationJank/src/android/windowanimationjank/FullscreenRotationTest.java
index 1fb502a..6792a8b 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/FullscreenRotationTest.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/FullscreenRotationTest.java
@@ -17,8 +17,9 @@
 package android.windowanimationjank;
 
 import android.os.Bundle;
-import android.support.test.jank.JankTest;
-import android.support.test.jank.GfxMonitor;
+
+import androidx.test.jank.GfxMonitor;
+import androidx.test.jank.JankTest;
 
 /**
  * Detect janks during screen rotation for full-screen activity. Periodically change
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
index bf739fa..a8ace162 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
@@ -16,12 +16,10 @@
 
 package android.windowanimationjank;
 
-import java.io.IOException;
-import java.util.StringTokenizer;
-
-import android.support.test.jank.JankTestBase;
 import android.support.test.uiautomator.UiDevice;
 
+import androidx.test.jank.JankTestBase;
+
 /**
  * This adds additional system level jank monitor and its result is merged with primary monitor
  * used in test.
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 7e1b400..2ef141f 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -14,7 +14,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     frameworks-base-testutils \
     framework-protos \
-    android-support-test \
+    androidx.test.rules \
     mockito-target-minus-junit4 \
     platform-test-annotations \
     services.core \
diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml
index 6dae3f1..dcacb6d 100644
--- a/tests/net/AndroidManifest.xml
+++ b/tests/net/AndroidManifest.xml
@@ -51,7 +51,7 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.frameworks.tests.net"
         android:label="Frameworks Networking Tests" />
 </manifest>
diff --git a/tests/net/AndroidTest.xml b/tests/net/AndroidTest.xml
index 6e020a3..939ae49 100644
--- a/tests/net/AndroidTest.xml
+++ b/tests/net/AndroidTest.xml
@@ -22,7 +22,7 @@
     <option name="test-tag" value="FrameworksNetTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.tests.net" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
index 25e1474..fd555c1 100644
--- a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
+++ b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -38,9 +37,10 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index 6174c6c..7ede144 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -34,7 +34,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
@@ -47,19 +46,20 @@
 import static org.mockito.Mockito.when;
 
 import android.app.PendingIntent;
-import android.net.ConnectivityManager;
-import android.net.NetworkCapabilities;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkCapabilities;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
-import android.content.pm.ApplicationInfo;
-import android.os.Build.VERSION_CODES;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/DnsPacketTest.java b/tests/net/java/android/net/DnsPacketTest.java
index 032e526..91ff6b3 100644
--- a/tests/net/java/android/net/DnsPacketTest.java
+++ b/tests/net/java/android/net/DnsPacketTest.java
@@ -20,8 +20,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index eae9710..57ecc8f 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -17,8 +17,9 @@
 package android.net;
 
 import android.content.Context;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/IpPrefixTest.java b/tests/net/java/android/net/IpPrefixTest.java
index 1f1ba2e..3cc0e36 100644
--- a/tests/net/java/android/net/IpPrefixTest.java
+++ b/tests/net/java/android/net/IpPrefixTest.java
@@ -25,15 +25,16 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.net.InetAddress;
 import java.util.Random;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class IpPrefixTest {
diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/tests/net/java/android/net/IpSecAlgorithmTest.java
index 85e8361..8e9d08c 100644
--- a/tests/net/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/net/java/android/net/IpSecAlgorithmTest.java
@@ -20,17 +20,18 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.AbstractMap.SimpleEntry;
 import java.util.Arrays;
 import java.util.Map.Entry;
 import java.util.Random;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 /** Unit tests for {@link IpSecAlgorithm}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
index be1a455..215506c 100644
--- a/tests/net/java/android/net/IpSecConfigTest.java
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -22,7 +22,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
index 8160924..730e2d5 100644
--- a/tests/net/java/android/net/IpSecManagerTest.java
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -19,6 +19,7 @@
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
@@ -30,21 +31,22 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.test.mock.MockContext;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.Os;
+import android.test.mock.MockContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.IpSecService;
 
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
 /** Unit tests for {@link IpSecManager}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/android/net/IpSecTransformTest.java b/tests/net/java/android/net/IpSecTransformTest.java
index ffd1f06..2308a3c 100644
--- a/tests/net/java/android/net/IpSecTransformTest.java
+++ b/tests/net/java/android/net/IpSecTransformTest.java
@@ -19,7 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/LinkAddressTest.java b/tests/net/java/android/net/LinkAddressTest.java
index c1ad946..be7bd1b 100644
--- a/tests/net/java/android/net/LinkAddressTest.java
+++ b/tests/net/java/android/net/LinkAddressTest.java
@@ -26,6 +26,7 @@
 import static android.system.OsConstants.RT_SCOPE_LINK;
 import static android.system.OsConstants.RT_SCOPE_SITE;
 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -33,24 +34,22 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.net.Inet4Address;
-import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 
-import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class LinkAddressTest {
diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
index bdde096..9a7d487 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -24,11 +24,12 @@
 
 import android.net.LinkProperties.CompareResult;
 import android.net.LinkProperties.ProvisioningChange;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.OsConstants;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.TestUtils;
 
 import org.junit.Test;
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 17486e0..daf187d 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 84f7359..4d4915b 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -42,10 +42,11 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/net/java/android/net/NetworkStatsHistoryTest.java b/tests/net/java/android/net/NetworkStatsHistoryTest.java
index 301d04d..13558cd 100644
--- a/tests/net/java/android/net/NetworkStatsHistoryTest.java
+++ b/tests/net/java/android/net/NetworkStatsHistoryTest.java
@@ -16,14 +16,14 @@
 
 package android.net;
 
+import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong;
+import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong;
+import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
 import static android.net.NetworkStatsHistory.FIELD_ALL;
 import static android.net.NetworkStatsHistory.FIELD_OPERATIONS;
 import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
 import static android.net.NetworkStatsHistory.FIELD_RX_PACKETS;
 import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLong;
-import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLong;
-import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
 import static android.net.TrafficStats.GB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
@@ -32,29 +32,30 @@
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.tests.net.R;
 
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.util.Random;
 
-import org.junit.After;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetworkStatsHistoryTest {
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 2c2afd4..b5b0384 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -19,6 +19,7 @@
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.INTERFACES_ALL;
 import static android.net.NetworkStats.METERED_ALL;
 import static android.net.NetworkStats.METERED_NO;
@@ -26,31 +27,30 @@
 import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DBG_VPN_IN;
 import static android.net.NetworkStats.SET_DBG_VPN_OUT;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import android.net.NetworkStats.Entry;
 import android.os.Process;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.google.android.collect.Sets;
 
-import java.util.HashSet;
-
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashSet;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/NetworkTest.java b/tests/net/java/android/net/NetworkTest.java
index 94d01e9..0bee7cd 100644
--- a/tests/net/java/android/net/NetworkTest.java
+++ b/tests/net/java/android/net/NetworkTest.java
@@ -25,22 +25,22 @@
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.net.Network;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
-import java.io.IOException;
 import java.net.DatagramSocket;
-import java.net.InetAddress;
 import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.net.SocketException;
 import java.util.Objects;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetworkTest {
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index ba6e0f2..7748288 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -18,7 +18,7 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -27,7 +27,7 @@
 import java.util.TreeSet;
 
 @RunWith(AndroidJUnit4.class)
-@android.support.test.filters.SmallTest
+@androidx.test.filters.SmallTest
 public class NetworkUtilsTest {
     @Test
     public void testRoutedIPv4AddressCount() {
diff --git a/tests/net/java/android/net/StaticIpConfigurationTest.java b/tests/net/java/android/net/StaticIpConfigurationTest.java
index 2b5ad37..8449ca7 100644
--- a/tests/net/java/android/net/StaticIpConfigurationTest.java
+++ b/tests/net/java/android/net/StaticIpConfigurationTest.java
@@ -23,8 +23,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/UidRangeTest.java b/tests/net/java/android/net/UidRangeTest.java
index 860d732..ea1df09 100644
--- a/tests/net/java/android/net/UidRangeTest.java
+++ b/tests/net/java/android/net/UidRangeTest.java
@@ -16,15 +16,13 @@
 
 package android.net;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java b/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java
index 40a8b3e..f948086 100644
--- a/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java
+++ b/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java
@@ -20,14 +20,13 @@
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.net.MalformedURLException;
-import java.net.URL;
 import java.text.ParseException;
 
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java
index 4a6f20a..e01ac7f 100644
--- a/tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpServingParamsParcelExtTest.java
@@ -25,8 +25,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.LinkAddress;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/ip/InterfaceControllerTest.java b/tests/net/java/android/net/ip/InterfaceControllerTest.java
index d27a4f9..7a56b3a 100644
--- a/tests/net/java/android/net/ip/InterfaceControllerTest.java
+++ b/tests/net/java/android/net/ip/InterfaceControllerTest.java
@@ -28,8 +28,9 @@
 import android.net.InterfaceConfigurationParcel;
 import android.net.LinkAddress;
 import android.net.util.SharedLog;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/ip/IpServerTest.java b/tests/net/java/android/net/ip/IpServerTest.java
index f7542a7..05912e8 100644
--- a/tests/net/java/android/net/ip/IpServerTest.java
+++ b/tests/net/java/android/net/ip/IpServerTest.java
@@ -65,10 +65,11 @@
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
index 1fc67a8..76cccc9 100644
--- a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
+++ b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java
@@ -21,8 +21,9 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
index 3aab942..5c86757 100644
--- a/tests/net/java/android/net/netlink/ConntrackMessageTest.java
+++ b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
@@ -20,19 +20,18 @@
 import static org.junit.Assume.assumeTrue;
 
 import android.system.OsConstants;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import libcore.util.HexEncoding;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
-import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.Arrays;
-
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index 122edba..b6038ab 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -25,8 +25,6 @@
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
 import static android.system.OsConstants.SOCK_STREAM;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVTIMEO;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -38,29 +36,25 @@
 import android.net.ConnectivityManager;
 import android.net.netlink.StructNlMsgHdr;
 import android.os.Process;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
-import android.support.test.InstrumentationRegistry;
 import android.system.Os;
-import android.system.StructTimeval;
-import android.util.Log;
-import java.io.FileDescriptor;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.util.HexEncoding;
 
 import org.junit.Before;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileDescriptor;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
index 6647760..44ab605 100644
--- a/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkErrorMessageTest.java
@@ -16,9 +16,10 @@
 
 package android.net.netlink;
 
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
 import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
 import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -27,18 +28,17 @@
 import android.net.netlink.NetlinkErrorMessage;
 import android.net.netlink.NetlinkMessage;
 import android.net.netlink.StructNlMsgErr;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
-import android.util.Log;
 
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import org.junit.runner.RunWith;
-import org.junit.Test;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.util.HexEncoding;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/netlink/NetlinkSocketTest.java b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
index 11be40b..3916578 100644
--- a/tests/net/java/android/net/netlink/NetlinkSocketTest.java
+++ b/tests/net/java/android/net/netlink/NetlinkSocketTest.java
@@ -18,31 +18,29 @@
 
 import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
 import static android.system.OsConstants.NETLINK_ROUTE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.net.netlink.NetlinkSocket;
 import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
-import android.system.ErrnoException;
 import android.system.NetlinkSocketAddress;
 import android.system.Os;
-import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import libcore.io.IoUtils;
 
-import java.io.InterruptedIOException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.FileDescriptor;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetlinkSocketTest {
diff --git a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
index c9fd74f..8162522 100644
--- a/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/tests/net/java/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -25,23 +25,22 @@
 import android.net.netlink.RtNetlinkNeighborMessage;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
 import android.system.OsConstants;
-import android.util.Log;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import libcore.util.HexEncoding;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Arrays;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-import libcore.util.HexEncoding;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class RtNetlinkNeighborMessageTest {
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index 0a5a6aa..2d2bccb 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -16,29 +16,31 @@
 
 package android.net.nsd;
 
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static com.android.internal.util.TestUtils.waitForIdleHandler;
 
-import android.os.HandlerThread;
-import android.os.Handler;
-import android.os.Looper;
 import android.content.Context;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.AsyncChannel;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -46,8 +48,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.Consumer;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NsdManagerTest {
diff --git a/tests/net/java/android/net/nsd/NsdServiceInfoTest.java b/tests/net/java/android/net/nsd/NsdServiceInfoTest.java
index e48b522..94dfc75 100644
--- a/tests/net/java/android/net/nsd/NsdServiceInfoTest.java
+++ b/tests/net/java/android/net/nsd/NsdServiceInfoTest.java
@@ -24,20 +24,18 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.StrictMode;
-import android.net.nsd.NsdServiceInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Map;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NsdServiceInfoTest {
diff --git a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java b/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
index 6da8514..35f8c79 100644
--- a/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
+++ b/tests/net/java/android/net/shared/Inet4AddressUtilsTest.java
@@ -32,8 +32,9 @@
 import static org.junit.Assert.fail;
 
 import android.net.InetAddresses;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/shared/InitialConfigurationTest.java b/tests/net/java/android/net/shared/InitialConfigurationTest.java
index 78792bd..27bc13d 100644
--- a/tests/net/java/android/net/shared/InitialConfigurationTest.java
+++ b/tests/net/java/android/net/shared/InitialConfigurationTest.java
@@ -24,8 +24,9 @@
 
 import android.net.IpPrefix;
 import android.net.LinkAddress;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
index fb4d43c..3e86e77 100644
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
@@ -27,8 +27,9 @@
 import android.net.LinkAddress;
 import android.net.StaticIpConfiguration;
 import android.net.apf.ApfCapabilities;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
index b6d01db..2d0e03d 100644
--- a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
+++ b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
@@ -29,8 +29,9 @@
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
 import android.net.Uri;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
index 6ea47d2..6fad89e 100644
--- a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
+++ b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java
@@ -27,8 +27,9 @@
 import android.net.Network;
 import android.net.StaticIpConfiguration;
 import android.net.apf.ApfCapabilities;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/android/net/util/InterfaceParamsTest.java b/tests/net/java/android/net/util/InterfaceParamsTest.java
index 21728af..141455c 100644
--- a/tests/net/java/android/net/util/InterfaceParamsTest.java
+++ b/tests/net/java/android/net/util/InterfaceParamsTest.java
@@ -21,13 +21,12 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class InterfaceParamsTest {
diff --git a/tests/net/java/android/net/util/InterfaceSetTest.java b/tests/net/java/android/net/util/InterfaceSetTest.java
index 8012838..ea084b6 100644
--- a/tests/net/java/android/net/util/InterfaceSetTest.java
+++ b/tests/net/java/android/net/util/InterfaceSetTest.java
@@ -20,8 +20,8 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/util/IpUtilsTest.java b/tests/net/java/android/net/util/IpUtilsTest.java
index 8903bf9..193d85d 100644
--- a/tests/net/java/android/net/util/IpUtilsTest.java
+++ b/tests/net/java/android/net/util/IpUtilsTest.java
@@ -18,14 +18,14 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.nio.ByteBuffer;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class IpUtilsTest {
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
index 8604860..e1dba36 100644
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -19,16 +19,14 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Vector;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java b/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java
index 39f59f1..0d27d5b 100644
--- a/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java
+++ b/tests/net/java/android/net/util/VersionedBroadcastListenerTest.java
@@ -26,21 +26,19 @@
 import android.os.Looper;
 import android.os.UserHandle;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.test.BroadcastInterceptingContext;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class VersionedBroadcastListenerTest {
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index 90bf7b1..4ec4fdd 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -24,33 +24,36 @@
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+
 import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import android.content.res.Resources;
 import android.net.NetworkStats;
 import android.net.TrafficStats;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.tests.net.R;
 
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
-import org.junit.runner.RunWith;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 /**
  * Tests for {@link NetworkStatsFactory}.
  */
diff --git a/tests/net/java/com/android/internal/util/BitUtilsTest.java b/tests/net/java/com/android/internal/util/BitUtilsTest.java
index f4dc12a..01fb0df 100644
--- a/tests/net/java/com/android/internal/util/BitUtilsTest.java
+++ b/tests/net/java/com/android/internal/util/BitUtilsTest.java
@@ -16,14 +16,24 @@
 
 package com.android.internal.util;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import java.nio.ByteBuffer;
+import static com.android.internal.util.BitUtils.bytesToBEInt;
+import static com.android.internal.util.BitUtils.bytesToLEInt;
+import static com.android.internal.util.BitUtils.getUint16;
+import static com.android.internal.util.BitUtils.getUint32;
+import static com.android.internal.util.BitUtils.getUint8;
+import static com.android.internal.util.BitUtils.uint16;
+import static com.android.internal.util.BitUtils.uint32;
+import static com.android.internal.util.BitUtils.uint8;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static org.junit.Assert.assertEquals;
-import static com.android.internal.util.BitUtils.*;
+import java.nio.ByteBuffer;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/com/android/internal/util/RingBufferTest.java b/tests/net/java/com/android/internal/util/RingBufferTest.java
index 90a373a..eff334f 100644
--- a/tests/net/java/com/android/internal/util/RingBufferTest.java
+++ b/tests/net/java/com/android/internal/util/RingBufferTest.java
@@ -16,19 +16,18 @@
 
 package com.android.internal.util;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
+
 import java.util.Arrays;
 import java.util.Objects;
 
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RingBufferTest {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1a0e8fa..d29234f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -148,15 +148,16 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.util.ArrayUtils;
@@ -205,7 +206,6 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Predicate;
 
-
 /**
  * Tests for {@link ConnectivityService}.
  *
@@ -939,11 +939,19 @@
             return mConnected;  // Similar trickery
         }
 
-        public void connect() {
+        private void connect(boolean isAlwaysMetered) {
             mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
             mConnected = true;
             mConfig = new VpnConfig();
-            mConfig.isMetered = false;
+            mConfig.isMetered = isAlwaysMetered;
+        }
+
+        public void connectAsAlwaysMetered() {
+            connect(true /* isAlwaysMetered */);
+        }
+
+        public void connect() {
+            connect(false /* isAlwaysMetered */);
         }
 
         @Override
@@ -5104,6 +5112,202 @@
     }
 
     @Test
+    public void testIsActiveNetworkMeteredOverWifi() {
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+        waitForIdle();
+
+        assertFalse(mCm.isActiveNetworkMetered());
+    }
+
+    @Test
+    public void testIsActiveNetworkMeteredOverCell() {
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellNetworkAgent.connect(true);
+        waitForIdle();
+
+        assertTrue(mCm.isActiveNetworkMetered());
+    }
+
+    @Test
+    public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellNetworkAgent.connect(true);
+        waitForIdle();
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // Connect VPN network. By default it is using current default network (Cell).
+        MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        final int uid = Process.myUid();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true);
+        mMockVpn.connect();
+        waitForIdle();
+        // Ensure VPN is now the active network.
+        assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+        // Expect VPN to be metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // Connect WiFi.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+        waitForIdle();
+        // VPN should still be the active network.
+        assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+        // Expect VPN to be unmetered as it should now be using WiFi (new default).
+        assertFalse(mCm.isActiveNetworkMetered());
+
+        // Disconnecting Cell should not affect VPN's meteredness.
+        mCellNetworkAgent.disconnect();
+        waitForIdle();
+
+        assertFalse(mCm.isActiveNetworkMetered());
+
+        // Disconnect WiFi; Now there is no platform default network.
+        mWiFiNetworkAgent.disconnect();
+        waitForIdle();
+
+        // VPN without any underlying networks is treated as metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        vpnNetworkAgent.disconnect();
+        mMockVpn.disconnect();
+    }
+
+   @Test
+   public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED);
+        mCellNetworkAgent.connect(true);
+        waitForIdle();
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+        waitForIdle();
+        assertFalse(mCm.isActiveNetworkMetered());
+
+        // Connect VPN network.
+        MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        final int uid = Process.myUid();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true);
+        mMockVpn.connect();
+        waitForIdle();
+        // Ensure VPN is now the active network.
+        assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        // VPN is using Cell
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork() });
+        waitForIdle();
+
+        // Expect VPN to be metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // VPN is now using WiFi
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mWiFiNetworkAgent.getNetwork() });
+        waitForIdle();
+
+        // Expect VPN to be unmetered
+        assertFalse(mCm.isActiveNetworkMetered());
+
+        // VPN is using Cell | WiFi.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+        waitForIdle();
+
+        // Expect VPN to be metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // VPN is using WiFi | Cell.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mWiFiNetworkAgent.getNetwork(), mCellNetworkAgent.getNetwork() });
+        waitForIdle();
+
+        // Order should not matter and VPN should still be metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // VPN is not using any underlying networks.
+        mService.setUnderlyingNetworksForVpn(new Network[0]);
+        waitForIdle();
+
+        // VPN without underlying networks is treated as metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        vpnNetworkAgent.disconnect();
+        mMockVpn.disconnect();
+    }
+
+    @Test
+    public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
+        // Returns true by default when no network is available.
+        assertTrue(mCm.isActiveNetworkMetered());
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+        waitForIdle();
+        assertFalse(mCm.isActiveNetworkMetered());
+
+        // Connect VPN network.
+        MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        final int uid = Process.myUid();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true);
+        mMockVpn.connectAsAlwaysMetered();
+        waitForIdle();
+        assertEquals(vpnNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+        // VPN is tracking current platform default (WiFi).
+        mService.setUnderlyingNetworksForVpn(null);
+        waitForIdle();
+
+        // Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // VPN explicitly declares WiFi as its underlying network.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mWiFiNetworkAgent.getNetwork() });
+        waitForIdle();
+
+        // Doesn't really matter whether VPN declares its underlying networks explicitly.
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        // With WiFi lost, VPN is basically without any underlying networks. And in that case it is
+        // anyways suppose to be metered.
+        mWiFiNetworkAgent.disconnect();
+        waitForIdle();
+
+        assertTrue(mCm.isActiveNetworkMetered());
+
+        vpnNetworkAgent.disconnect();
+    }
+
+    @Test
     public void testNetworkBlockedStatus() {
         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
         final NetworkRequest cellRequest = new NetworkRequest.Builder()
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index a844cfe..7c40adf 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -18,6 +18,7 @@
 
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
@@ -45,13 +46,10 @@
 import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
-import android.support.test.filters.SmallTest;
 import android.system.Os;
 import android.test.mock.MockContext;
 
-import java.net.Socket;
-import java.util.Arrays;
-import java.util.Collection;
+import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -59,6 +57,10 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Collection;
+
 /** Unit tests for {@link IpSecService}. */
 @SmallTest
 @RunWith(Parameterized.class)
diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
index cf8f715..68ff777 100644
--- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java
@@ -31,22 +31,23 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.IpSecService.IResource;
 import com.android.server.IpSecService.RefcountedResource;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ThreadLocalRandom;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 /** Unit tests for {@link IpSecService.RefcountedResource}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 5be7c7b..b5c3e92 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -20,6 +20,7 @@
 import static android.system.OsConstants.EADDRINUSE;
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
@@ -39,19 +40,24 @@
 import android.net.IpSecConfig;
 import android.net.IpSecManager;
 import android.net.IpSecSpiResponse;
-import android.net.IpSecTransform;
 import android.net.IpSecUdpEncapResponse;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructStat;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import dalvik.system.SocketTagger;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+
 import java.io.FileDescriptor;
 import java.net.InetAddress;
 import java.net.ServerSocket;
@@ -60,11 +66,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-
 /** Unit tests for {@link IpSecService}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index 56a075b..6fb3225 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -26,21 +26,19 @@
 import android.content.Context;
 import android.net.INetd;
 import android.net.LinkAddress;
-import android.net.LocalSocket;
 import android.net.LocalServerSocket;
+import android.net.LocalSocket;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.app.IBatteryStats;
 import com.android.server.NetworkManagementService.SystemServices;
 import com.android.server.net.BaseNetworkObserver;
 
-import java.io.IOException;
-import java.io.OutputStream;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -48,6 +46,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.IOException;
+import java.io.OutputStream;
+
 /**
  * Tests for {@link NetworkManagementService}.
  */
diff --git a/tests/net/java/com/android/server/NsdServiceTest.java b/tests/net/java/com/android/server/NsdServiceTest.java
index b88c784..a90fa68 100644
--- a/tests/net/java/com/android/server/NsdServiceTest.java
+++ b/tests/net/java/com/android/server/NsdServiceTest.java
@@ -22,23 +22,25 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.content.Context;
-import android.content.ContentResolver;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.NsdService.DaemonConnection;
 import com.android.server.NsdService.DaemonConnectionSupplier;
 import com.android.server.NsdService.NativeCallbackReceiver;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
index 38322e9..15ba43d 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -37,10 +37,11 @@
 import android.net.shared.PrivateDnsConfig;
 import android.os.INetworkManagementService;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.test.FakeSettingsProvider;
 
 import org.junit.Before;
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 0656c5f..70495cc 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -16,52 +16,44 @@
 
 package com.android.server.connectivity;
 
-import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
-import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
-import static com.android.server.connectivity.MetricsTestUtil.aBool;
-import static com.android.server.connectivity.MetricsTestUtil.aByteArray;
 import static com.android.server.connectivity.MetricsTestUtil.aLong;
 import static com.android.server.connectivity.MetricsTestUtil.aString;
 import static com.android.server.connectivity.MetricsTestUtil.aType;
 import static com.android.server.connectivity.MetricsTestUtil.anInt;
-import static com.android.server.connectivity.MetricsTestUtil.anIntArray;
-import static com.android.server.connectivity.MetricsTestUtil.b;
 import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.BLUETOOTH;
 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.CELLULAR;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ETHERNET;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.MULTIPLE;
 import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.WIFI;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
 import android.net.ConnectivityMetricsEvent;
 import android.net.metrics.ApfProgramEvent;
 import android.net.metrics.ApfStats;
-import android.net.metrics.ConnectStats;
 import android.net.metrics.DefaultNetworkEvent;
 import android.net.metrics.DhcpClientEvent;
 import android.net.metrics.DhcpErrorEvent;
-import android.net.metrics.DnsEvent;
-import android.net.metrics.DnsEvent;
 import android.net.metrics.IpManagerEvent;
 import android.net.metrics.IpReachabilityEvent;
 import android.net.metrics.NetworkEvent;
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
 import android.net.metrics.WakeupStats;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.Arrays;
 import java.util.List;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 1a0cb74..d5b2c87 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -47,11 +47,12 @@
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
 import android.os.Parcelable;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.BitUtils;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
 
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 5057443..6de4aa1 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -39,10 +39,11 @@
 import android.net.NetworkInfo;
 import android.net.NetworkMisc;
 import android.os.INetworkManagementService;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.format.DateUtils;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.server.ConnectivityService;
 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index e58811b..b783467 100644
--- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -28,7 +28,6 @@
 import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
 import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
 
-import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertNotNull;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -54,13 +53,14 @@
 import android.net.StringNetworkSpecifier;
 import android.os.Handler;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.util.DataUnit;
 import android.util.RecurrenceRule;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.LocalServices;
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index 37c0df8..cc09fb7 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -37,8 +37,9 @@
 import android.os.Handler;
 import android.os.INetworkManagementService;
 import android.os.test.TestLooper;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.ConnectivityService;
 
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 67805c9..e4117b8 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -18,43 +18,37 @@
 
 import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
 import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
 
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
 
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetdEventListenerServiceTest {
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 273b8fc..9580763 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -35,10 +35,11 @@
 import android.content.res.Resources;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
 
 import org.junit.Before;
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index f2bd770..354c08f 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -50,8 +50,9 @@
 import android.os.Build;
 import android.os.INetworkManagementService;
 import android.os.UserHandle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 533d7ad..a12b0a0 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -98,11 +98,12 @@
 import android.os.UserManager;
 import android.os.test.TestLooper;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.test.BroadcastInterceptingContext;
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index b5d1ff9..2cae250 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -73,11 +73,12 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.net.VpnConfig;
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 193f380..3944fad 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -42,11 +42,12 @@
 import android.os.ResultReceiver;
 import android.os.test.TestLooper;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -225,7 +226,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
 
@@ -241,7 +242,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 3. No cache value and ui entitlement check is needed.
@@ -254,7 +255,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         mLooper.dispatchAll();
         callbackTimeoutHelper(mCallbacklatch);
         assertTrue(mEnMgr.everRunUiEntitlement);
@@ -268,7 +269,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed.
@@ -281,7 +282,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         mLooper.dispatchAll();
         callbackTimeoutHelper(mCallbacklatch);
         assertTrue(mEnMgr.everRunUiEntitlement);
@@ -295,7 +296,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_WIFI, receiver, true);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_WIFI, receiver, true);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
         // 7. Test get value for other downstream type.
@@ -307,7 +308,7 @@
                 mCallbacklatch.countDown();
             }
         };
-        mEnMgr.getLatestTetheringEntitlementValue(TETHERING_USB, receiver, false);
+        mEnMgr.getLatestTetheringEntitlementResult(TETHERING_USB, receiver, false);
         callbackTimeoutHelper(mCallbacklatch);
         assertFalse(mEnMgr.everRunUiEntitlement);
     }
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index b98f63b..be54b1a 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -23,7 +23,9 @@
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
 import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+
 import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -35,7 +37,6 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -52,30 +53,30 @@
 import android.net.util.SharedLog;
 import android.os.ConditionVariable;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
-import com.android.internal.util.test.FakeSettingsProvider;
 
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.test.FakeSettingsProvider;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index f8cfd8f..36a1b7c 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -36,11 +36,12 @@
 import android.content.res.Resources;
 import android.net.util.SharedLog;
 import android.provider.Settings;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 0afd607..5a1f853 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -41,8 +41,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.IConnectivityManager;
@@ -54,16 +52,19 @@
 import android.net.NetworkRequest;
 import android.net.NetworkState;
 import android.net.util.SharedLog;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.os.Handler;
+import android.os.Message;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -76,7 +77,6 @@
 import java.util.Objects;
 import java.util.Set;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class UpstreamNetworkMonitorTest {
diff --git a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
index b870bbd..6e725dd 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
@@ -26,10 +26,11 @@
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.LocalServices;
 
 import org.junit.After;
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 6f14332..830c928 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -26,12 +26,13 @@
 import static android.os.Process.myUid;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+
+import static com.android.server.net.NetworkStatsCollection.multiplySafe;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
-import static com.android.server.net.NetworkStatsCollection.multiplySafe;
-
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.NetworkIdentity;
@@ -40,20 +41,26 @@
 import android.net.NetworkTemplate;
 import android.os.Process;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.SubscriptionPlan;
 import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.text.format.DateUtils;
 import android.util.RecurrenceRule;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.tests.net.R;
 
 import libcore.io.IoUtils;
 import libcore.io.Streams;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
@@ -68,11 +75,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 /**
  * Tests for {@link NetworkStatsCollection}.
  */
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 185c3eb..43a3803 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -17,7 +17,6 @@
 package com.android.server.net;
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.METERED_NO;
@@ -33,11 +32,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.when;
 
 import android.app.usage.NetworkStatsManager;
 import android.net.DataUsageRequest;
@@ -49,22 +45,17 @@
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Message;
 import android.os.Messenger;
 import android.os.Process;
 import android.os.UserHandle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 
-import com.android.internal.net.VpnInfo;
-import com.android.server.net.NetworkStatsService;
-import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import java.util.ArrayList;
-import java.util.Objects;
-import java.util.List;
+import com.android.internal.net.VpnInfo;
+import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -73,6 +64,8 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Objects;
+
 /**
  * Tests for {@link NetworkStatsObservers}.
  */
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index d91d3eb..598448b 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -91,15 +91,15 @@
 import android.os.Messenger;
 import android.os.PowerManager;
 import android.os.SimpleClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.TelephonyManager;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.net.VpnInfo;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.server.LocalServices;
 import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
 import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
 
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
index e57433a..be10680 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -39,9 +39,10 @@
 import android.net.ipmemorystore.StatusParcelable;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index fe19eee..dc20185 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.net.ipmemorystore.NetworkAttributes;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java b/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
index 8d367e2..7413b91 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
@@ -22,8 +22,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index bc3a9a1..8bef221 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -141,6 +141,7 @@
         "ResourceValues.cpp",
         "SdkConstants.cpp",
         "StringPool.cpp",
+        "trace/TraceBuffer.cpp",
         "xml/XmlActionExecutor.cpp",
         "xml/XmlDom.cpp",
         "xml/XmlPullParser.cpp",
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index adf85b0..39eb987 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -37,6 +37,7 @@
 #include "cmd/Link.h"
 #include "cmd/Optimize.h"
 #include "io/FileStream.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Util.h"
 
@@ -107,9 +108,12 @@
       : Command("daemon", "m"), out_(out), diagnostics_(diagnostics) {
     SetDescription("Runs aapt in daemon mode. Each subsequent line is a single parameter to the\n"
         "command. The end of an invocation is signaled by providing an empty line.");
+    AddOptionalFlag("--trace_folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
-  int Action(const std::vector<std::string>& /* args */) override {
+  int Action(const std::vector<std::string>& arguments) override {
+    TRACE_FLUSH_ARGS(trace_folder_ ? trace_folder_.value() : "", "daemon", arguments);
     text::Printer printer(out_);
     std::cout << "Ready" << std::endl;
 
@@ -150,6 +154,7 @@
  private:
   io::FileOutputStream* out_;
   IDiagnostics* diagnostics_;
+  Maybe<std::string> trace_folder_;
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index d0237f8..5e8d870 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -206,15 +206,6 @@
   }
 };
 
-// A chunk of text in the XML string within a CDATA tags.
-class CdataSegmentNode : public SegmentNode {
- public:
-
-  void Build(StringBuilder* builder) const override {
-    builder->AppendText(data, /* preserve_spaces */ true);
-  }
-};
-
 // A tag that will be encoded into the final flattened string. Tags like <b> or <i>.
 class SpanNode : public Node {
  public:
@@ -251,7 +242,6 @@
   std::vector<Node*> node_stack;
   node_stack.push_back(&root);
 
-  bool cdata_block = false;
   bool saw_span_node = false;
   SegmentNode* first_segment = nullptr;
   SegmentNode* last_segment = nullptr;
@@ -262,12 +252,9 @@
 
     // First take care of any SegmentNodes that should be created.
     if (event == xml::XmlPullParser::Event::kStartElement
-        || event == xml::XmlPullParser::Event::kEndElement
-        || event == xml::XmlPullParser::Event::kCdataStart
-        || event == xml::XmlPullParser::Event::kCdataEnd) {
+        || event == xml::XmlPullParser::Event::kEndElement) {
       if (!current_text.empty()) {
-        std::unique_ptr<SegmentNode> segment_node = (cdata_block)
-            ? util::make_unique<CdataSegmentNode>() : util::make_unique<SegmentNode>();
+        auto segment_node = util::make_unique<SegmentNode>();
         segment_node->data = std::move(current_text);
 
         last_segment = node_stack.back()->AddChild(std::move(segment_node));
@@ -345,16 +332,6 @@
         }
       } break;
 
-      case xml::XmlPullParser::Event::kCdataStart: {
-        cdata_block = true;
-        break;
-      }
-
-      case xml::XmlPullParser::Event::kCdataEnd: {
-        cdata_block = false;
-        break;
-      }
-
       default:
         // ignore.
         break;
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 25b76b0..251ca0c 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -1195,27 +1195,26 @@
 }
 
 TEST_F(ResourceParserTest, ParseCData) {
-  std::string input = R"(
-      <string name="foo"><![CDATA[some text and ' apostrophe]]></string>)";
-
+  // Double quotes should still change the state of whitespace processing
+  std::string input = R"(<string name="foo">Hello<![CDATA[ "</string>' ]]>      World</string>)";
   ASSERT_TRUE(TestParse(input));
-  String* output = test::GetValue<String>(&table_, "string/foo");
+  auto output = test::GetValue<String>(&table_, "string/foo");
   ASSERT_THAT(output, NotNull());
-  EXPECT_THAT(*output, StrValueEq("some text and ' apostrophe"));
+  EXPECT_THAT(*output, StrValueEq(std::string("Hello </string>'       World").data()));
 
-  // Double quotes should not change the state of whitespace processing
-  input = R"(<string name="foo2">Hello<![CDATA[ "</string>' ]]>      World</string>)";
+  input = R"(<string name="foo2"><![CDATA[Hello
+                                          World]]></string>)";
   ASSERT_TRUE(TestParse(input));
   output = test::GetValue<String>(&table_, "string/foo2");
   ASSERT_THAT(output, NotNull());
-  EXPECT_THAT(*output, StrValueEq(std::string("Hello \"</string>'  World").data()));
+  EXPECT_THAT(*output, StrValueEq(std::string("Hello World").data()));
 
-  // Cdata blocks should not have their whitespace trimmed
+  // Cdata blocks should have their whitespace trimmed
   input = R"(<string name="foo3">     <![CDATA[ text ]]>     </string>)";
   ASSERT_TRUE(TestParse(input));
   output = test::GetValue<String>(&table_, "string/foo3");
   ASSERT_THAT(output, NotNull());
-  EXPECT_THAT(*output, StrValueEq(std::string(" text ").data()));
+  EXPECT_THAT(*output, StrValueEq(std::string("text").data()));
 
   input = R"(<string name="foo4">     <![CDATA[]]>     </string>)";
   ASSERT_TRUE(TestParse(input));
@@ -1227,7 +1226,11 @@
   ASSERT_TRUE(TestParse(input));
   output = test::GetValue<String>(&table_, "string/foo5");
   ASSERT_THAT(output, NotNull());
-  EXPECT_THAT(*output, StrValueEq(std::string("    ").data()));
+  EXPECT_THAT(*output, StrValueEq(std::string("").data()));
+
+  // Single quotes must still be escaped
+  input = R"(<string name="foo6"><![CDATA[some text and ' apostrophe]]></string>)";
+  ASSERT_FALSE(TestParse(input));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index dbd0a0c..7c0619f 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -30,6 +30,7 @@
 #include "NameMangler.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 #include "text/Unicode.h"
 #include "util/Util.h"
 
@@ -79,6 +80,7 @@
 }
 
 ResourceTablePackage* ResourceTable::CreatePackage(const StringPiece& name, Maybe<uint8_t> id) {
+  TRACE_CALL();
   ResourceTablePackage* package = FindOrCreatePackage(name);
   if (id && !package->id) {
     package->id = id;
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index ffc1a92..f0e4d9e 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -845,20 +845,16 @@
     : preserve_spaces_(preserve_spaces), quote_(preserve_spaces) {
 }
 
-StringBuilder& StringBuilder::AppendText(const std::string& text, bool preserve_spaces) {
+StringBuilder& StringBuilder::AppendText(const std::string& text) {
   if (!error_.empty()) {
     return *this;
   }
 
-  // Enable preserving spaces if it is enabled for this append or the StringBuilder was constructed
-  // to preserve spaces
-  preserve_spaces = (preserve_spaces) ? preserve_spaces : preserve_spaces_;
-
   const size_t previous_len = xml_string_.text.size();
   Utf8Iterator iter(text);
   while (iter.HasNext()) {
     char32_t codepoint = iter.Next();
-    if (!preserve_spaces && !quote_ && codepoint != kNonBreakingSpace && iswspace(codepoint)) {
+    if (!preserve_spaces_ && !quote_ && codepoint != kNonBreakingSpace && iswspace(codepoint)) {
       if (!last_codepoint_was_space_) {
         // Emit a space if it's the first.
         xml_string_.text += ' ';
@@ -906,11 +902,11 @@
             break;
         }
       }
-    } else if (!preserve_spaces && codepoint == U'"') {
+    } else if (!preserve_spaces_ && codepoint == U'"') {
       // Only toggle the quote state when we are not preserving spaces.
       quote_ = !quote_;
 
-    } else if (!preserve_spaces && !quote_ && codepoint == U'\'') {
+    } else if (!preserve_spaces_ && !quote_ && codepoint == U'\'') {
       // This should be escaped when we are not preserving spaces
       error_ = StringPrintf("unescaped apostrophe in string\n\"%s\"", text.c_str());
       return *this;
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index a8a3120..f77766e 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -276,10 +276,8 @@
   // single quotations can be used without escaping them.
   explicit StringBuilder(bool preserve_spaces = false);
 
-  // Appends a chunk of text. If preserve_spaces is true, whitespace removal is not performed, and
-  // single quotations can be used without escaping them for this append. Otherwise, the
-  // StringBuilder will behave as it was constructed.
-  StringBuilder& AppendText(const std::string& text, bool preserve_spaces = false);
+  // Appends a chunk of text.
+  StringBuilder& AppendText(const std::string& text);
 
   // Starts a Span (tag) with the given name. The name is expected to be of the form:
   //  "tag_name;attr1=value;attr2=value;"
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 9018b0f..3b77135 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -266,29 +266,6 @@
 TEST(ResourceUtilsTest, StringBuilderPreserveSpaces) {
   EXPECT_THAT(ResourceUtils::StringBuilder(true /*preserve_spaces*/).AppendText("\"").to_string(),
               Eq("\""));
-
-  // Single quotes should be able to be used without escaping them when preserving spaces and the
-  // spaces should not be trimmed
-  EXPECT_THAT(ResourceUtils::StringBuilder()
-                  .AppendText("    hey guys ")
-                  .AppendText(" 'this is so cool' ", /* preserve_spaces */ true)
-                  .AppendText(" wow    ")
-                  .to_string(),
-              Eq(" hey guys  'this is so cool'  wow "));
-
-  // Reading a double quote while preserving spaces should not change the quote state
-  EXPECT_THAT(ResourceUtils::StringBuilder()
-                  .AppendText("    hey guys ")
-                  .AppendText(" \"this is so cool' ", /* preserve_spaces */ true)
-                  .AppendText(" wow    ")
-                  .to_string(),
-              Eq(" hey guys  \"this is so cool'  wow "));
-  EXPECT_THAT(ResourceUtils::StringBuilder()
-                  .AppendText("    hey guys\"  ")
-                  .AppendText(" \"this is so cool' ", /* preserve_spaces */ true)
-                  .AppendText(" wow  \"  ")
-                  .to_string(),
-              Eq(" hey guys   \"this is so cool'  wow   "));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Command.cpp b/tools/aapt2/cmd/Command.cpp
index 4424a35..919b4c9 100644
--- a/tools/aapt2/cmd/Command.cpp
+++ b/tools/aapt2/cmd/Command.cpp
@@ -25,6 +25,7 @@
 #include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using android::base::StringPrintf;
@@ -178,6 +179,7 @@
 }
 
 int Command::Execute(const std::vector<StringPiece>& args, std::ostream* out_error) {
+  TRACE_NAME_ARGS("Command::Execute", args);
   std::vector<std::string> file_args;
 
   for (size_t i = 0; i < args.size(); i++) {
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index bec6c69..42dc74c 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -45,6 +45,7 @@
 #include "io/StringStream.h"
 #include "io/Util.h"
 #include "io/ZipArchive.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Maybe.h"
 #include "util/Util.h"
@@ -141,6 +142,7 @@
 static bool CompileTable(IAaptContext* context, const CompileOptions& options,
                          const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                          const std::string& output_path) {
+  TRACE_CALL();
   ResourceTable table;
   {
     auto fin = file->OpenInputStream();
@@ -286,6 +288,7 @@
 static bool WriteHeaderAndDataToWriter(const StringPiece& output_path, const ResourceFile& file,
                                        io::KnownSizeInputStream* in, IArchiveWriter* writer,
                                        IDiagnostics* diag) {
+  TRACE_CALL();
   // Start the entry so we can write the header.
   if (!writer->StartEntry(output_path, 0)) {
     diag->Error(DiagMessage(output_path) << "failed to open file");
@@ -352,6 +355,7 @@
 static bool CompileXml(IAaptContext* context, const CompileOptions& options,
                        const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML");
   }
@@ -451,6 +455,7 @@
 static bool CompilePng(IAaptContext* context, const CompileOptions& options,
                        const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                        const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG");
   }
@@ -558,6 +563,7 @@
 static bool CompileFile(IAaptContext* context, const CompileOptions& options,
                         const ResourcePathData& path_data, io::IFile* file, IArchiveWriter* writer,
                         const std::string& output_path) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file");
   }
@@ -632,6 +638,7 @@
 
 int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
              CompileOptions& options) {
+  TRACE_CALL();
   bool error = false;
 
   // Iterate over the input files in a stable, platform-independent manner
@@ -707,6 +714,7 @@
 }
 
 int CompileCommand::Action(const std::vector<std::string>& args) {
+  TRACE_FLUSH(trace_folder_? trace_folder_.value() : "", "CompileCommand::Action");
   CompileContext context(diagnostic_);
   context.SetVerbose(options_.verbose);
 
diff --git a/tools/aapt2/cmd/Compile.h b/tools/aapt2/cmd/Compile.h
index 9b32cb3..d3456b2 100644
--- a/tools/aapt2/cmd/Compile.h
+++ b/tools/aapt2/cmd/Compile.h
@@ -60,6 +60,8 @@
         "Sets the visibility of the compiled resources to the specified\n"
             "level. Accepted levels: public, private, default", &visibility_);
     AddOptionalSwitch("-v", "Enables verbose logging", &options_.verbose);
+    AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
   int Action(const std::vector<std::string>& args) override;
@@ -68,6 +70,7 @@
   IDiagnostics* diagnostic_;
   CompileOptions options_;
   Maybe<std::string> visibility_;
+  Maybe<std::string> trace_folder_;
 };
 
 int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index a7b8d25..f354bb6 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -67,6 +67,7 @@
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
 #include "split/TableSplitter.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "xml/XmlDom.h"
 
@@ -213,6 +214,7 @@
 static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
                        const StringPiece& path, bool keep_raw_values, bool utf16,
                        OutputFormat format, IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
                                                       << (keep_raw_values ? "true" : "false")
@@ -250,6 +252,7 @@
 
 // Inflates an XML file from the source path.
 static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
+  TRACE_CALL();
   FileInputStream fin(path);
   if (fin.HadError()) {
     diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
@@ -421,6 +424,7 @@
 
 std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile(
     ResourceTable* table, FileOperation* file_op) {
+  TRACE_CALL();
   xml::XmlResource* doc = file_op->xml_to_flatten.get();
   const Source& src = doc->file.source;
 
@@ -489,6 +493,7 @@
 };
 
 bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
+  TRACE_CALL();
   bool error = false;
   std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
 
@@ -806,6 +811,7 @@
   // Creates a SymbolTable that loads symbols from the various APKs.
   // Pre-condition: context_->GetCompilationPackage() needs to be set.
   bool LoadSymbolsFromIncludePaths() {
+    TRACE_NAME("LoadSymbolsFromIncludePaths: #" + std::to_string(options_.include_paths.size()));
     auto asset_source = util::make_unique<AssetManagerSymbolSource>();
     for (const std::string& path : options_.include_paths) {
       if (context_->IsVerbose()) {
@@ -891,6 +897,7 @@
   }
 
   Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
+    TRACE_CALL();
     // Make sure the first element is <manifest> with package attribute.
     xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
     if (manifest_el == nullptr) {
@@ -1041,6 +1048,7 @@
   }
 
   bool FlattenTable(ResourceTable* table, OutputFormat format, IArchiveWriter* writer) {
+    TRACE_CALL();
     switch (format) {
       case OutputFormat::kApk: {
         BigBuffer buffer(1024);
@@ -1114,6 +1122,7 @@
   }
 
   bool GenerateJavaClasses() {
+    TRACE_CALL();
     // The set of packages whose R class to call in the main classes onResourcesLoaded callback.
     std::vector<std::string> packages_to_callback;
 
@@ -1197,6 +1206,7 @@
   }
 
   bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
+    TRACE_CALL();
     if (!options_.generate_java_class_path) {
       return true;
     }
@@ -1254,6 +1264,7 @@
   }
 
   bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
+    TRACE_CALL();
     if (!out) {
       return true;
     }
@@ -1278,6 +1289,7 @@
   }
 
   bool MergeStaticLibrary(const std::string& input, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
     }
@@ -1328,6 +1340,7 @@
 
   bool MergeExportedSymbols(const Source& source,
                             const std::vector<SourcedResourceName>& exported_symbols) {
+    TRACE_CALL();
     // Add the exports of this file to the table.
     for (const SourcedResourceName& exported_symbol : exported_symbols) {
       ResourceName res_name = exported_symbol.name;
@@ -1353,6 +1366,7 @@
   }
 
   bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage()
                                        << "merging '" << compiled_file.name
@@ -1371,6 +1385,7 @@
   // An io::IFileCollection is created from the ZIP file and added to the set of
   // io::IFileCollections that are open.
   bool MergeArchive(const std::string& input, bool override) {
+    TRACE_CALL();
     if (context_->IsVerbose()) {
       context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
     }
@@ -1418,6 +1433,7 @@
   // All other file types are ignored. This is because these files could be coming from a zip,
   // where we could have other files like classes.dex.
   bool MergeFile(io::IFile* file, bool override) {
+    TRACE_CALL();
     const Source& src = file->GetSource();
 
     if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
@@ -1458,6 +1474,7 @@
 
     while ((entry = reader.Next()) != nullptr) {
       if (entry->Type() == ContainerEntryType::kResTable) {
+        TRACE_NAME(std::string("Process ResTable:") + file->GetSource().path);
         pb::ResourceTable pb_table;
         if (!entry->GetResTable(&pb_table)) {
           context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read resource table: "
@@ -1478,6 +1495,7 @@
           return false;
         }
       } else if (entry->Type() == ContainerEntryType::kResFile) {
+        TRACE_NAME(std::string("Process ResFile") + file->GetSource().path);
         pb::internal::CompiledFile pb_compiled_file;
         off64_t offset;
         size_t len;
@@ -1551,6 +1569,7 @@
   // to the IArchiveWriter.
   bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
                 ResourceTable* table) {
+    TRACE_CALL();
     const bool keep_raw_values = (context_->GetPackageType() == PackageType::kStaticLib)
                                  || options_.keep_raw_values;
     bool result = FlattenXml(context_, *manifest, kAndroidManifestPath, keep_raw_values,
@@ -1632,6 +1651,7 @@
   }
 
   int Run(const std::vector<std::string>& input_files) {
+    TRACE_CALL();
     // Load the AndroidManifest.xml
     std::unique_ptr<xml::XmlResource> manifest_xml =
         LoadXml(options_.manifest_path, context_->GetDiagnostics());
@@ -1839,6 +1859,7 @@
       std::vector<ConfigDescription> excluded_configs;
 
       for (auto& config_string : options_.exclude_configs_) {
+        TRACE_NAME("ConfigDescription::Parse");
         ConfigDescription config_description;
 
         if (!ConfigDescription::Parse(config_string, &config_description)) {
@@ -2038,6 +2059,7 @@
 };
 
 int LinkCommand::Action(const std::vector<std::string>& args) {
+  TRACE_FLUSH(trace_folder_ ? trace_folder_.value() : "", "LinkCommand::Action");
   LinkContext context(diag_);
 
   // Expand all argument-files passed into the command line. These start with '@'.
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 1fc149a..7c58385 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -25,6 +25,7 @@
 #include "split/TableSplitter.h"
 #include "format/binary/TableFlattener.h"
 #include "link/ManifestFixer.h"
+#include "trace/TraceBuffer.h"
 
 namespace aapt {
 
@@ -277,6 +278,8 @@
         "Do not allow overlays with different visibility levels.",
         &options_.strict_visibility);
     AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
+    AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
+                    &trace_folder_);
   }
 
   int Action(const std::vector<std::string>& args) override;
@@ -300,6 +303,7 @@
   bool proto_format_ = false;
   Maybe<std::string> stable_id_file_path_;
   std::vector<std::string> split_args_;
+  Maybe<std::string> trace_folder_;
 };
 
 }// namespace aapt
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 33122dc..d396d81 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -27,6 +27,7 @@
 #include "androidfw/ResourceTypes.h"
 
 #include "Source.h"
+#include "trace/TraceBuffer.h"
 #include "util/BigBuffer.h"
 #include "util/Util.h"
 
@@ -1233,6 +1234,7 @@
 
 bool Png::process(const Source& source, std::istream* input,
                   BigBuffer* outBuffer, const PngOptions& options) {
+  TRACE_CALL();
   png_byte signature[kPngSignatureSize];
 
   // Read the PNG signature first.
diff --git a/tools/aapt2/compile/PngCrunch.cpp b/tools/aapt2/compile/PngCrunch.cpp
index 0346a19..1f4ea44d 100644
--- a/tools/aapt2/compile/PngCrunch.cpp
+++ b/tools/aapt2/compile/PngCrunch.cpp
@@ -27,6 +27,8 @@
 #include "android-base/logging.h"
 #include "android-base/macros.h"
 
+#include "trace/TraceBuffer.h"
+
 namespace aapt {
 
 // Custom deleter that destroys libpng read and info structs.
@@ -142,6 +144,7 @@
 }
 
 std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) {
+  TRACE_CALL();
   // Create a diagnostics that has the source information encoded.
   SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
 
@@ -480,6 +483,7 @@
 bool WritePng(IAaptContext* context, const Image* image,
               const NinePatch* nine_patch, io::OutputStream* out,
               const PngOptions& options) {
+  TRACE_CALL();
   // Create and initialize the write png_struct with the default error and
   // warning handlers.
   // The header version is also passed in to ensure that this was built against the same
diff --git a/tools/aapt2/compile/XmlIdCollector.cpp b/tools/aapt2/compile/XmlIdCollector.cpp
index 2199d00..5054115 100644
--- a/tools/aapt2/compile/XmlIdCollector.cpp
+++ b/tools/aapt2/compile/XmlIdCollector.cpp
@@ -22,6 +22,7 @@
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
 #include "text/Unicode.h"
+#include "trace/TraceBuffer.h"
 #include "xml/XmlDom.h"
 
 namespace aapt {
@@ -72,6 +73,7 @@
 }  // namespace
 
 bool XmlIdCollector::Consume(IAaptContext* context, xml::XmlResource* xmlRes) {
+  TRACE_CALL();
   xmlRes->file.exported_symbols.clear();
   SourcePathDiagnostics source_diag(xmlRes->file.source, context->GetDiagnostics());
   IdCollector collector(&xmlRes->file.exported_symbols, &source_diag);
diff --git a/tools/aapt2/format/Container.cpp b/tools/aapt2/format/Container.cpp
index d4b4571..f189048 100644
--- a/tools/aapt2/format/Container.cpp
+++ b/tools/aapt2/format/Container.cpp
@@ -19,6 +19,8 @@
 #include "android-base/scopeguard.h"
 #include "android-base/stringprintf.h"
 
+#include "trace/TraceBuffer.h"
+
 using ::android::base::StringPrintf;
 using ::google::protobuf::io::CodedInputStream;
 using ::google::protobuf::io::CodedOutputStream;
@@ -171,6 +173,7 @@
 }
 
 bool ContainerReaderEntry::GetResTable(pb::ResourceTable* out_table) {
+  TRACE_CALL();
   CHECK(type_ == ContainerEntryType::kResTable) << "reading a kResTable when the type is kResFile";
   if (length_ > std::numeric_limits<int>::max()) {
     reader_->error_ = StringPrintf("entry length %zu is too large", length_);
@@ -261,6 +264,7 @@
       total_entry_count_(0u),
       current_entry_count_(0u),
       entry_(this) {
+  TRACE_CALL();
   ::google::protobuf::uint32 magic;
   if (!coded_in_.ReadLittleEndian32(&magic)) {
     std::ostringstream error;
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index d677317..aa578a2 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -32,6 +32,7 @@
 #include "ValueVisitor.h"
 #include "format/binary/ChunkWriter.h"
 #include "format/binary/ResourceTypeExtensions.h"
+#include "trace/TraceBuffer.h"
 #include "util/BigBuffer.h"
 
 using namespace android;
@@ -238,6 +239,7 @@
   }
 
   bool FlattenPackage(BigBuffer* buffer) {
+    TRACE_CALL();
     ChunkWriter pkg_writer(buffer);
     ResTable_package* pkg_header = pkg_writer.StartChunk<ResTable_package>(RES_TABLE_PACKAGE_TYPE);
     pkg_header->id = util::HostToDevice32(package_->id.value());
@@ -710,6 +712,7 @@
 }  // namespace
 
 bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_CALL();
   // We must do this before writing the resources, since the string pool IDs may change.
   table->string_pool.Prune();
   table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
diff --git a/tools/aapt2/format/binary/XmlFlattener.cpp b/tools/aapt2/format/binary/XmlFlattener.cpp
index 2fe2424..afbaae4 100644
--- a/tools/aapt2/format/binary/XmlFlattener.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener.cpp
@@ -99,9 +99,6 @@
     flat_node->lineNumber = util::HostToDevice32(node->line_number);
     flat_node->comment.index = util::HostToDevice32(-1);
 
-    // Process plain strings to make sure they get properly escaped.
-    text = StringBuilder(true /*preserve_spaces*/).AppendText(text).to_string();
-
     ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
     AddString(text, kLowPriority, &flat_text->data);
     writer.Finish();
diff --git a/tools/aapt2/format/binary/XmlFlattener_test.cpp b/tools/aapt2/format/binary/XmlFlattener_test.cpp
index 25786b1..1dac493 100644
--- a/tools/aapt2/format/binary/XmlFlattener_test.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener_test.cpp
@@ -118,7 +118,7 @@
   ASSERT_THAT(tree.getAttributeCount(), Eq(0u));
 
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
-  EXPECT_THAT(tree.getText(&len), StrEq(u"Some text\\"));
+  EXPECT_THAT(tree.getText(&len), StrEq(u"Some text\\\\"));
 
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
   EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
@@ -283,7 +283,7 @@
   EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\""));
 
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
-  EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
+  EXPECT_THAT(tree.getText(&len), StrEq(u"\\\\d{5}"));
 }
 
 TEST_F(XmlFlattenerTest, ProcessQuotes) {
@@ -360,6 +360,7 @@
    J
 
 </item>
+          <item>\t K \n </item>
           <item>
           </item>
       </root>)");
@@ -439,6 +440,12 @@
 
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
   EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+  EXPECT_THAT(tree.getText(&len), StrEq(u"\\t K \\n "));
+  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+  ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+  EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
   ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
 
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
index 9751632..ce6d9352 100644
--- a/tools/aapt2/io/Util.cpp
+++ b/tools/aapt2/io/Util.cpp
@@ -18,6 +18,8 @@
 
 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
+#include "trace/TraceBuffer.h"
+
 using ::android::StringPiece;
 using ::google::protobuf::io::ZeroCopyOutputStream;
 
@@ -26,6 +28,7 @@
 
 bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
                               uint32_t compression_flags, IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
   }
@@ -40,6 +43,7 @@
 
 bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path,
                        uint32_t compression_flags, IArchiveWriter* writer) {
+  TRACE_CALL();
   std::unique_ptr<io::IData> data = file->OpenAsData();
   if (!data) {
     context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
@@ -57,6 +61,7 @@
 bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
                         const std::string& out_path, uint32_t compression_flags,
                         IArchiveWriter* writer) {
+  TRACE_CALL();
   if (context->IsVerbose()) {
     context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
   }
@@ -83,6 +88,7 @@
 }
 
 bool Copy(OutputStream* out, InputStream* in) {
+  TRACE_CALL();
   const void* in_buffer;
   size_t in_len;
   while (in->Next(&in_buffer, &in_len)) {
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index 427dc92..f6aaa12 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -20,6 +20,7 @@
 #include "ziparchive/zip_archive.h"
 
 #include "Source.h"
+#include "trace/TraceBuffer.h"
 #include "util/Files.h"
 #include "util/Util.h"
 
@@ -93,6 +94,7 @@
 
 std::unique_ptr<ZipFileCollection> ZipFileCollection::Create(
     const StringPiece& path, std::string* out_error) {
+  TRACE_CALL();
   constexpr static const int32_t kEmptyArchive = -6;
 
   std::unique_ptr<ZipFileCollection> collection =
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 52e168e..05ba8f0 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -281,6 +281,15 @@
             AddClass(node->line_number, result.value(), "");
           }
         }
+
+        attr = node->FindAttribute(xml::kSchemaAndroid, "zygotePreloadName");
+        if (attr) {
+          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
+          if (result) {
+            AddClass(node->line_number, result.value(), "");
+          }
+        }
+
         if (main_dex_only_) {
           xml::Attribute* default_process = node->FindAttribute(xml::kSchemaAndroid, "process");
           if (default_process) {
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index da24907..559b07a 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -42,6 +42,7 @@
             android:appComponentFactory="com.foo.BarAppComponentFactory"
             android:backupAgent="com.foo.BarBackupAgent"
             android:name="com.foo.BarApplication"
+            android:zygotePreloadName="com.foo.BarZygotePreload"
             >
           <activity android:name="com.foo.BarActivity"/>
           <service android:name="com.foo.BarService"/>
@@ -63,6 +64,7 @@
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
 
   actual = GetKeepSetString(set, /** minimal_rules */ true);
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarAppComponentFactory { <init>(); }"));
@@ -73,6 +75,7 @@
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarReceiver { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarProvider { <init>(); }"));
   EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarInstrumentation { <init>(); }"));
+  EXPECT_THAT(actual, HasSubstr("-keep class com.foo.BarZygotePreload { <init>(); }"));
 }
 
 TEST(ProguardRulesTest, FragmentNameRuleIsEmitted) {
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index 960c7d4..73b9254 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -23,6 +23,7 @@
 #include "ResourceTable.h"
 #include "SdkConstants.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -70,6 +71,7 @@
 }
 
 bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("AutoVersioner::Consume");
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       if (type->type != ResourceType::kStyle) {
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 582a5b8..b0a2055 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -21,6 +21,7 @@
 #include "android-base/logging.h"
 
 #include "ResourceUtils.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
@@ -451,6 +452,7 @@
 }
 
 bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
+  TRACE_CALL();
   xml::Element* root = xml::FindRootElement(doc->root.get());
   if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
     context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/link/ProductFilter.cpp
index c1a95ee..793740a 100644
--- a/tools/aapt2/link/ProductFilter.cpp
+++ b/tools/aapt2/link/ProductFilter.cpp
@@ -17,6 +17,7 @@
 #include "link/Linkers.h"
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 namespace aapt {
 
@@ -81,6 +82,7 @@
 }
 
 bool ProductFilter::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ProductFilter::Consume");
   bool error = false;
   for (auto& pkg : table->packages) {
     for (auto& type : pkg->types) {
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index c2340ba..28f09aa 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -27,6 +27,7 @@
 #include "link/Linkers.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
@@ -353,6 +354,7 @@
 }
 
 bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ReferenceLinker::Consume");
   EmptyDeclStack decl_stack;
   bool error = false;
   for (auto& package : table->packages) {
diff --git a/tools/aapt2/link/ResourceExcluder.cpp b/tools/aapt2/link/ResourceExcluder.cpp
index 2555995..b3b9dc4 100644
--- a/tools/aapt2/link/ResourceExcluder.cpp
+++ b/tools/aapt2/link/ResourceExcluder.cpp
@@ -20,6 +20,7 @@
 
 #include "DominatorTree.h"
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -65,6 +66,7 @@
 }  // namespace
 
 bool ResourceExcluder::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("ResourceExcluder::Consume");
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index cc9fed5..e937517 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -21,6 +21,7 @@
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
+#include "trace/TraceBuffer.h"
 #include "ValueVisitor.h"
 #include "util/Util.h"
 
@@ -38,6 +39,7 @@
 }
 
 bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) {
+  TRACE_CALL();
   // We allow adding new resources if this is not an overlay, or if the options allow overlays
   // to add new resources.
   return MergeImpl(src, table, overlay, options_.auto_add_overlay || !overlay /*allow_new*/);
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 160ff92..d68f7dd 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -25,6 +25,7 @@
 #include "link/ReferenceLinker.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 #include "xml/XmlDom.h"
 
@@ -151,6 +152,7 @@
 }  // namespace
 
 bool XmlReferenceLinker::Consume(IAaptContext* context, xml::XmlResource* resource) {
+  TRACE_NAME("XmlReferenceLinker::Consume");
   CallSite callsite{resource->file.name.package};
 
   std::string out_name = resource->file.name.entry;
diff --git a/tools/aapt2/optimize/ResourceDeduper.cpp b/tools/aapt2/optimize/ResourceDeduper.cpp
index ee2dfbc..78ebcb9 100644
--- a/tools/aapt2/optimize/ResourceDeduper.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper.cpp
@@ -20,6 +20,7 @@
 
 #include "DominatorTree.h"
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -110,6 +111,7 @@
 }  // namespace
 
 bool ResourceDeduper::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_CALL();
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
       for (auto& entry : type->entries) {
diff --git a/tools/aapt2/optimize/VersionCollapser.cpp b/tools/aapt2/optimize/VersionCollapser.cpp
index f985604..cd791bd 100644
--- a/tools/aapt2/optimize/VersionCollapser.cpp
+++ b/tools/aapt2/optimize/VersionCollapser.cpp
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 
 using android::ConfigDescription;
 
@@ -144,6 +145,7 @@
 }
 
 bool VersionCollapser::Consume(IAaptContext* context, ResourceTable* table) {
+  TRACE_NAME("VersionCollapser::Consume");
   const int min_sdk = context->GetMinSdkVersion();
   for (auto& package : table->packages) {
     for (auto& type : package->types) {
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 78e0074..61a8fbb 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -30,6 +30,7 @@
 #include "Resource.h"
 #include "ResourceUtils.h"
 #include "ValueVisitor.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using ::android::ApkAssets;
@@ -217,6 +218,7 @@
 }
 
 bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
+  TRACE_CALL();
   if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) {
     apk_assets_.push_back(std::move(apk));
 
@@ -233,6 +235,7 @@
 }
 
 std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
+  TRACE_CALL();
   std::map<size_t, std::string> package_map;
   asset_manager_.ForEachPackage([&package_map](const std::string& name, uint8_t id) -> bool {
     package_map.insert(std::make_pair(id, name));
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 24cd5ba..6a67271 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -27,6 +27,7 @@
 #include "androidfw/ConfigDescription.h"
 
 #include "ResourceTable.h"
+#include "trace/TraceBuffer.h"
 #include "util/Util.h"
 
 using ::android::ConfigDescription;
@@ -154,6 +155,7 @@
   }
 }
 bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
+  TRACE_CALL();
   bool error = false;
   for (size_t i = 0; i < split_constraints_.size(); i++) {
     if (split_constraints_[i].configs.size() == 0) {
diff --git a/tools/aapt2/trace/TraceBuffer.cpp b/tools/aapt2/trace/TraceBuffer.cpp
new file mode 100644
index 0000000..b4b31d9
--- /dev/null
+++ b/tools/aapt2/trace/TraceBuffer.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "TraceBuffer.h"
+
+#include <chrono>
+#include <sstream>
+#include <unistd.h>
+#include <vector>
+
+#include <inttypes.h>
+
+#include "android-base/utf8.h"
+
+#include "util/Files.h"
+
+namespace aapt {
+namespace tracebuffer {
+
+namespace {
+
+constexpr char kBegin = 'B';
+constexpr char kEnd = 'E';
+
+struct TracePoint {
+  pid_t tid;
+  int64_t time;
+  std::string tag;
+  char type;
+};
+
+std::vector<TracePoint> traces;
+
+int64_t GetTime() noexcept {
+  auto now = std::chrono::steady_clock::now();
+  return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
+}
+
+} // namespace anonymous
+
+void AddWithTime(const std::string& tag, char type, int64_t time) noexcept {
+  TracePoint t = {getpid(), time, tag, type};
+  traces.emplace_back(t);
+}
+
+void Add(const std::string& tag, char type) noexcept {
+  AddWithTime(tag, type, GetTime());
+}
+
+
+
+
+void Flush(const std::string& basePath) {
+  TRACE_CALL();
+  if (basePath.empty()) {
+    return;
+  }
+
+  std::stringstream s;
+  s << basePath << aapt::file::sDirSep << "report_aapt2_" << getpid() << ".json";
+  FILE* f = android::base::utf8::fopen(s.str().c_str(), "a");
+  if (f == nullptr) {
+    return;
+  }
+
+  for(const TracePoint& trace : traces) {
+    fprintf(f, "{\"ts\" : \"%" PRIu64 "\", \"ph\" : \"%c\", \"tid\" : \"%d\" , \"pid\" : \"%d\", "
+            "\"name\" : \"%s\" },\n", trace.time, trace.type, 0, trace.tid, trace.tag.c_str());
+  }
+  fclose(f);
+  traces.clear();
+}
+
+} // namespace tracebuffer
+
+void BeginTrace(const std::string& tag) {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+void EndTrace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+}
+
+Trace::Trace(const std::string& tag) {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+Trace::Trace(const std::string& tag, const std::vector<android::StringPiece>& args) {
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg.to_string();
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+Trace::~Trace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag)
+    : basepath_(basepath)  {
+  tracebuffer::Add(tag, tracebuffer::kBegin);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
+    const std::vector<android::StringPiece>& args) : basepath_(basepath) {
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg.to_string();
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+FlushTrace::FlushTrace(const std::string& basepath, const std::string& tag,
+    const std::vector<std::string>& args) : basepath_(basepath){
+  std::stringstream s;
+  s << tag;
+  s << " ";
+  for (auto& arg : args) {
+    s << arg;
+    s << " ";
+  }
+  tracebuffer::Add(s.str(), tracebuffer::kBegin);
+}
+
+FlushTrace::~FlushTrace() {
+  tracebuffer::Add("", tracebuffer::kEnd);
+  tracebuffer::Flush(basepath_);
+}
+
+} // namespace aapt
+
diff --git a/tools/aapt2/trace/TraceBuffer.h b/tools/aapt2/trace/TraceBuffer.h
new file mode 100644
index 0000000..8618e0e
--- /dev/null
+++ b/tools/aapt2/trace/TraceBuffer.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_TRACEBUFFER_H
+#define AAPT_TRACEBUFFER_H
+
+#include <string>
+#include <vector>
+
+#include <androidfw/StringPiece.h>
+
+namespace aapt {
+
+// Record timestamps for beginning and end of a task and generate systrace json fragments.
+// This is an in-process ftrace which has the advantage of being platform independent.
+// These methods are NOT thread-safe since aapt2 is not multi-threaded.
+
+// Convenience RIAA object to automatically finish an event when object goes out of scope.
+class Trace {
+public:
+  Trace(const std::string& tag);
+  Trace(const std::string& tag, const std::vector<android::StringPiece>& args);
+  ~Trace();
+};
+
+// Manual markers.
+void BeginTrace(const std::string& tag);
+void EndTrace();
+
+// A master trace is required to flush events to disk. Events are formatted in systrace
+// json format.
+class FlushTrace {
+public:
+  explicit FlushTrace(const std::string& basepath, const std::string& tag);
+  explicit FlushTrace(const std::string& basepath, const std::string& tag,
+      const std::vector<android::StringPiece>& args);
+  explicit FlushTrace(const std::string& basepath, const std::string& tag,
+      const std::vector<std::string>& args);
+  ~FlushTrace();
+private:
+  std::string basepath_;
+};
+
+#define TRACE_CALL() Trace __t(__func__)
+#define TRACE_NAME(tag) Trace __t(tag)
+#define TRACE_NAME_ARGS(tag, args) Trace __t(tag, args)
+
+#define TRACE_FLUSH(basename, tag) FlushTrace __t(basename, tag)
+#define TRACE_FLUSH_ARGS(basename, tag, args) FlushTrace __t(basename, tag, args)
+} // namespace aapt
+#endif //AAPT_TRACEBUFFER_H
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index acd07c2..9a725fa 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -26,6 +26,7 @@
 #include "android-base/logging.h"
 
 #include "ResourceUtils.h"
+#include "trace/TraceBuffer.h"
 #include "XmlPullParser.h"
 #include "util/Util.h"
 
@@ -264,6 +265,7 @@
 }
 
 std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
+  TRACE_CALL();
   // We import the android namespace because on Windows NO_ERROR is a macro, not
   // an enum, which causes errors when qualifying it with android::
   using namespace android;
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 295e3de..f967c2f 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -170,6 +170,7 @@
         self.ctors = []
         self.fields = []
         self.methods = []
+        self.annotations = []
 
         if sig_format == 2:
             V2LineParser(raw).parse_into_class(self)
@@ -196,8 +197,10 @@
 
             if "implements" in raw:
                 self.implements = raw[raw.index("implements")+1]
+                self.implements_all = [self.implements]
             else:
                 self.implements = None
+                self.implements_all = []
         else:
             raise ValueError("Unknown signature format: " + sig_format)
 
@@ -224,7 +227,7 @@
 
 
 class Package():
-    NAME = re.compile("package(?: .*)? ([A-Za-z.]+)")
+    NAME = re.compile("package(?: .*)? ([A-Za-z0-9.]+)")
 
     def __init__(self, line, raw, blame):
         self.line = line
@@ -351,8 +354,8 @@
 
     def parse_into_class(self, clazz):
         clazz.split = []
-        annotations = self.parse_annotations()
-        if "@Deprecated" in annotations:
+        clazz.annotations = self.parse_annotations()
+        if "@Deprecated" in clazz.annotations:
             clazz.split.append("deprecated")
         clazz.split.extend(self.parse_modifiers())
         kind = self.parse_one_of("class", "interface", "@interface", "enum")
@@ -364,12 +367,12 @@
         self.parse_matching_paren("<", ">")
         extends = self.parse_extends()
         clazz.extends = extends[0] if extends else None
-        implements = self.parse_implements()
-        clazz.implements = implements[0] if implements else None
+        clazz.implements_all = self.parse_implements()
         # The checks assume that interfaces are always found in implements, which isn't true for
         # subinterfaces.
-        if not implements and "interface" in clazz.split:
-            clazz.implements = clazz.extends
+        if not clazz.implements_all and "interface" in clazz.split:
+            clazz.implements_all = [clazz.extends]
+        clazz.implements = clazz.implements_all[0] if clazz.implements_all else None
         self.parse_token("{")
         self.parse_eof()
 
@@ -761,6 +764,14 @@
     noticed[clazz.fullname] = hash(clazz)
 
 
+verifiers = {}
+
+def verifier(f):
+    verifiers[f.__name__] = f
+    return f
+
+
+@verifier
 def verify_constants(clazz):
     """All static final constants must be FOO_NAME style."""
     if re.match("android\.R\.[a-z]+", clazz.fullname): return
@@ -778,13 +789,13 @@
             if f.typ in req and f.value is None:
                 error(clazz, f, None, "All constants must be defined at compile time")
 
-
+@verifier
 def verify_enums(clazz):
     """Enums are bad, mmkay?"""
     if clazz.extends == "java.lang.Enum" or "enum" in clazz.split:
         error(clazz, None, "F5", "Enums are not allowed")
 
-
+@verifier
 def verify_class_names(clazz):
     """Try catching malformed class names like myMtp or MTPUser."""
     if clazz.fullname.startswith("android.opengl"): return
@@ -799,6 +810,7 @@
         error(clazz, None, None, "Don't expose your implementation details")
 
 
+@verifier
 def verify_method_names(clazz):
     """Try catching malformed method names, like Foo() or getMTU()."""
     if clazz.fullname.startswith("android.opengl"): return
@@ -812,9 +824,9 @@
             error(clazz, m, "S1", "Method name must start with lowercase char")
 
 
+@verifier
 def verify_callbacks(clazz):
     """Verify Callback classes.
-    All callback classes must be abstract.
     All methods must follow onFoo() naming style."""
     if clazz.fullname == "android.speech.tts.SynthesisCallback": return
 
@@ -824,14 +836,12 @@
         warn(clazz, None, "L1", "Class should be named FooCallback")
 
     if clazz.name.endswith("Callback"):
-        if "interface" in clazz.split:
-            error(clazz, None, "CL3", "Callbacks must be abstract class to enable extension in future API levels")
-
         for m in clazz.methods:
             if not re.match("on[A-Z][a-z]*", m.name):
                 error(clazz, m, "L1", "Callback method names must be onFoo() style")
 
 
+@verifier
 def verify_listeners(clazz):
     """Verify Listener classes.
     All Listener classes must be interface.
@@ -853,6 +863,7 @@
                 error(clazz, m, "L1", "Single listener method name must match class name")
 
 
+@verifier
 def verify_actions(clazz):
     """Verify intent actions.
     All action names must be named ACTION_FOO.
@@ -884,6 +895,7 @@
                         error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected))
 
 
+@verifier
 def verify_extras(clazz):
     """Verify intent extras.
     All extra names must be named EXTRA_FOO.
@@ -914,6 +926,7 @@
                         error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected))
 
 
+@verifier
 def verify_equals(clazz):
     """Verify that equals() and hashCode() must be overridden together."""
     eq = False
@@ -926,6 +939,7 @@
         error(clazz, None, "M8", "Must override both equals and hashCode; missing one")
 
 
+@verifier
 def verify_parcelable(clazz):
     """Verify that Parcelable objects aren't hiding required bits."""
     if clazz.implements == "android.os.Parcelable":
@@ -944,6 +958,7 @@
                 error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors")
 
 
+@verifier
 def verify_protected(clazz):
     """Verify that no protected methods or fields are allowed."""
     for m in clazz.methods:
@@ -955,6 +970,7 @@
             error(clazz, f, "M7", "Protected fields not allowed; must be public")
 
 
+@verifier
 def verify_fields(clazz):
     """Verify that all exposed fields are final.
     Exposed fields must follow myName style.
@@ -1000,6 +1016,7 @@
                 error(clazz, f, "C2", "Constants must be marked static final")
 
 
+@verifier
 def verify_register(clazz):
     """Verify parity of registration methods.
     Callback objects use register/unregister methods.
@@ -1033,6 +1050,7 @@
                 error(clazz, m, "L3", "Listener methods should be named add/remove")
 
 
+@verifier
 def verify_sync(clazz):
     """Verify synchronized methods aren't exposed."""
     for m in clazz.methods:
@@ -1040,6 +1058,7 @@
             error(clazz, m, "M5", "Internal locks must not be exposed")
 
 
+@verifier
 def verify_intent_builder(clazz):
     """Verify that Intent builders are createFooIntent() style."""
     if clazz.name == "Intent": return
@@ -1052,6 +1071,7 @@
                 warn(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()")
 
 
+@verifier
 def verify_helper_classes(clazz):
     """Verify that helper classes are named consistently with what they extend.
     All developer extendable methods should be named onFoo()."""
@@ -1100,6 +1120,7 @@
                     warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
 
 
+@verifier
 def verify_builder(clazz):
     """Verify builder classes.
     Methods should return the builder to enable chaining."""
@@ -1132,12 +1153,14 @@
         error(clazz, None, None, "Builder should be final")
 
 
+@verifier
 def verify_aidl(clazz):
     """Catch people exposing raw AIDL."""
     if clazz.extends == "android.os.Binder" or clazz.implements == "android.os.IInterface":
         error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
 
 
+@verifier
 def verify_internal(clazz):
     """Catch people exposing internal classes."""
     if clazz.pkg.name.startswith("com.android"):
@@ -1172,6 +1195,7 @@
     "android.util"
 ])
 
+@verifier
 def verify_layering(clazz):
     """Catch package layering violations.
     For example, something in android.os depending on android.app."""
@@ -1206,6 +1230,7 @@
                 warn(clazz, m, "FW6", "Method argument type violates package layering")
 
 
+@verifier
 def verify_boolean(clazz):
     """Verifies that boolean accessors are named correctly.
     For example, hasFoo() and setHasFoo()."""
@@ -1246,9 +1271,11 @@
                 error_if_exists(sets, m.name, expected, "has" + target)
 
 
+@verifier
 def verify_collections(clazz):
     """Verifies that collection types are interfaces."""
     if clazz.fullname == "android.os.Bundle": return
+    if clazz.fullname == "android.os.Parcel": return
 
     bad = ["java.util.Vector", "java.util.LinkedList", "java.util.ArrayList", "java.util.Stack",
            "java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
@@ -1260,6 +1287,23 @@
                 error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
 
 
+@verifier
+def verify_uris(clazz):
+    bad = ["java.net.URL", "java.net.URI", "android.net.URL"]
+
+    for f in clazz.fields:
+        if f.typ in bad:
+            error(clazz, f, None, "Field must be android.net.Uri instead of " + f.typ)
+
+    for m in clazz.methods + clazz.ctors:
+        if m.typ in bad:
+            error(clazz, m, None, "Must return android.net.Uri instead of " + m.typ)
+        for arg in m.args:
+            if arg in bad:
+                error(clazz, m, None, "Argument must take android.net.Uri instead of " + arg)
+
+
+@verifier
 def verify_flags(clazz):
     """Verifies that flags are non-overlapping."""
     known = collections.defaultdict(int)
@@ -1276,6 +1320,7 @@
             known[scope] |= val
 
 
+@verifier
 def verify_exception(clazz):
     """Verifies that methods don't throw generic exceptions."""
     for m in clazz.methods:
@@ -1284,17 +1329,19 @@
                 error(clazz, m, "S1", "Methods must not throw generic exceptions")
 
             if t in ["android.os.RemoteException"]:
-                if clazz.name == "android.content.ContentProviderClient": continue
-                if clazz.name == "android.os.Binder": continue
-                if clazz.name == "android.os.IBinder": continue
+                if clazz.fullname == "android.content.ContentProviderClient": continue
+                if clazz.fullname == "android.os.Binder": continue
+                if clazz.fullname == "android.os.IBinder": continue
 
                 error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
 
             if len(m.args) == 0 and t in ["java.lang.IllegalArgumentException", "java.lang.NullPointerException"]:
                 warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException")
 
+
 GOOGLE_IGNORECASE = re.compile("google", re.IGNORECASE)
 
+# Not marked as @verifier, because it is only conditionally applied.
 def verify_google(clazz):
     """Verifies that APIs never reference Google."""
 
@@ -1307,6 +1354,7 @@
                 error(clazz, t, None, "Must never reference Google")
 
 
+@verifier
 def verify_bitset(clazz):
     """Verifies that we avoid using heavy BitSet."""
 
@@ -1322,6 +1370,7 @@
                 error(clazz, m, None, "Argument type must not be heavy BitSet")
 
 
+@verifier
 def verify_manager(clazz):
     """Verifies that FooManager is only obtained from Context."""
 
@@ -1335,6 +1384,7 @@
             error(clazz, m, None, "Managers must always be obtained from Context")
 
 
+@verifier
 def verify_boxed(clazz):
     """Verifies that methods avoid boxed primitives."""
 
@@ -1357,6 +1407,7 @@
                 error(clazz, m, "M11", "Must avoid boxed primitives")
 
 
+@verifier
 def verify_static_utils(clazz):
     """Verifies that helper classes can't be constructed."""
     if clazz.fullname.startswith("android.opengl"): return
@@ -1376,6 +1427,7 @@
         error(clazz, None, None, "Fully-static utility classes must not have constructor")
 
 
+# @verifier  # Disabled for now
 def verify_overload_args(clazz):
     """Verifies that method overloads add new arguments at the end."""
     if clazz.fullname.startswith("android.opengl"): return
@@ -1416,6 +1468,7 @@
                 error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig)))
 
 
+@verifier
 def verify_callback_handlers(clazz):
     """Verifies that methods adding listener/callback have overload
     for specifying delivery thread."""
@@ -1467,6 +1520,7 @@
             warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Executor")
 
 
+@verifier
 def verify_context_first(clazz):
     """Verifies that methods accepting a Context keep it the first argument."""
     examine = clazz.ctors + clazz.methods
@@ -1479,6 +1533,7 @@
                 error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument")
 
 
+@verifier
 def verify_listener_last(clazz):
     """Verifies that methods accepting a Listener or Callback keep them as last arguments."""
     examine = clazz.ctors + clazz.methods
@@ -1492,6 +1547,7 @@
                 warn(clazz, m, "M3", "Listeners should always be at end of argument list")
 
 
+@verifier
 def verify_resource_names(clazz):
     """Verifies that resource names have consistent case."""
     if not re.match("android\.R\.[a-z]+", clazz.fullname): return
@@ -1523,6 +1579,7 @@
             error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
 
 
+@verifier
 def verify_files(clazz):
     """Verifies that methods accepting File also accept streams."""
 
@@ -1544,6 +1601,7 @@
             warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
 
 
+@verifier
 def verify_manager_list(clazz):
     """Verifies that managers return List<? extends Parcelable> instead of arrays."""
 
@@ -1554,6 +1612,7 @@
             warn(clazz, m, None, "Methods should return List<? extends Parcelable> instead of Parcelable[] to support ParceledListSlice under the hood")
 
 
+@verifier
 def verify_abstract_inner(clazz):
     """Verifies that abstract inner classes are static."""
 
@@ -1562,6 +1621,7 @@
             warn(clazz, None, None, "Abstract inner classes should be static to improve testability")
 
 
+@verifier
 def verify_runtime_exceptions(clazz):
     """Verifies that runtime exceptions aren't listed in throws."""
 
@@ -1606,6 +1666,7 @@
                 error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses")
 
 
+@verifier
 def verify_error(clazz):
     """Verifies that we always use Exception instead of Error."""
     if not clazz.extends: return
@@ -1615,6 +1676,7 @@
         error(clazz, None, None, "Exceptions must be named FooException")
 
 
+@verifier
 def verify_units(clazz):
     """Verifies that we use consistent naming for units."""
 
@@ -1651,10 +1713,11 @@
             error(clazz, m, None, "Percentage must use ints")
 
 
+@verifier
 def verify_closable(clazz):
     """Verifies that classes are AutoClosable."""
-    if clazz.implements == "java.lang.AutoCloseable": return
-    if clazz.implements == "java.io.Closeable": return
+    if "java.lang.AutoCloseable" in clazz.implements_all: return
+    if "java.io.Closeable" in clazz.implements_all: return
 
     for m in clazz.methods:
         if len(m.args) > 0: continue
@@ -1663,6 +1726,7 @@
             return
 
 
+@verifier
 def verify_member_name_not_kotlin_keyword(clazz):
     """Prevent method names which are keywords in Kotlin."""
 
@@ -1688,6 +1752,7 @@
             error(clazz, f, None, "Field name must not be a Kotlin keyword")
 
 
+@verifier
 def verify_method_name_not_kotlin_operator(clazz):
     """Warn about method names which become operators in Kotlin."""
 
@@ -1737,6 +1802,7 @@
             unique_binary_op(m, m.name[:-6])  # Remove 'Assign' suffix
 
 
+@verifier
 def verify_collections_over_arrays(clazz):
     """Warn that [] should be Collections."""
 
@@ -1752,6 +1818,7 @@
                 warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array")
 
 
+@verifier
 def verify_user_handle(clazz):
     """Methods taking UserHandle should be ForUser or AsUser."""
     if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return
@@ -1776,6 +1843,7 @@
                  "or 'queryFooForUser'")
 
 
+@verifier
 def verify_params(clazz):
     """Parameter classes should be 'Params'."""
     if clazz.name.endswith("Params"): return
@@ -1791,6 +1859,7 @@
             error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'")
 
 
+@verifier
 def verify_services(clazz):
     """Service name should be FOO_BAR_SERVICE = 'foo_bar'."""
     if clazz.fullname != "android.content.Context": return
@@ -1804,6 +1873,7 @@
                 error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected))
 
 
+@verifier
 def verify_tense(clazz):
     """Verify tenses of method names."""
     if clazz.fullname.startswith("android.opengl"): return
@@ -1813,6 +1883,7 @@
             warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
 
 
+@verifier
 def verify_icu(clazz):
     """Verifies that richer ICU replacements are used."""
     better = {
@@ -1844,6 +1915,7 @@
                 warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg]))
 
 
+@verifier
 def verify_clone(clazz):
     """Verify that clone() isn't implemented; see EJ page 61."""
     for m in clazz.methods:
@@ -1851,8 +1923,12 @@
             error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
 
 
+@verifier
 def verify_pfd(clazz):
     """Verify that android APIs use PFD over FD."""
+    if clazz.fullname == "android.os.FileUtils" or clazz.fullname == "android.system.Os":
+        return
+
     examine = clazz.ctors + clazz.methods
     for m in examine:
         if m.typ == "java.io.FileDescriptor":
@@ -1869,6 +1945,7 @@
             error(clazz, f, "FW11", "Must use ParcelFileDescriptor")
 
 
+@verifier
 def verify_numbers(clazz):
     """Discourage small numbers types like short and byte."""
 
@@ -1890,8 +1967,10 @@
             if arg in discouraged:
                 warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
 
+
 PRIMITIVES = {"void", "int", "float", "boolean", "short", "char", "byte", "long", "double"}
 
+@verifier
 def verify_nullability(clazz):
     """Catches missing nullability annotations"""
 
@@ -1920,6 +1999,18 @@
 def has_nullability(annotations):
     return "@NonNull" in annotations or "@Nullable" in annotations
 
+
+@verifier
+def verify_intdef(clazz):
+    """intdefs must be @hide, because the constant names cannot be stored in
+       the stubs (only the values are, which is not useful)"""
+    if "@interface" not in clazz.split:
+        return
+    if "@IntDef" in clazz.annotations or "@LongDef" in clazz.annotations:
+        error(clazz, None, None, "@IntDef and @LongDef annotations must be @hide")
+
+
+@verifier
 def verify_singleton(clazz):
     """Catch singleton objects with constructors."""
 
@@ -1954,60 +2045,10 @@
 
     if not is_interesting(clazz): return
 
-    verify_constants(clazz)
-    verify_enums(clazz)
-    verify_class_names(clazz)
-    verify_method_names(clazz)
-    verify_callbacks(clazz)
-    verify_listeners(clazz)
-    verify_actions(clazz)
-    verify_extras(clazz)
-    verify_equals(clazz)
-    verify_parcelable(clazz)
-    verify_protected(clazz)
-    verify_fields(clazz)
-    verify_register(clazz)
-    verify_sync(clazz)
-    verify_intent_builder(clazz)
-    verify_helper_classes(clazz)
-    verify_builder(clazz)
-    verify_aidl(clazz)
-    verify_internal(clazz)
-    verify_layering(clazz)
-    verify_boolean(clazz)
-    verify_collections(clazz)
-    verify_flags(clazz)
-    verify_exception(clazz)
+    for v in verifiers.itervalues():
+        v(clazz)
+
     if not ALLOW_GOOGLE: verify_google(clazz)
-    verify_bitset(clazz)
-    verify_manager(clazz)
-    verify_boxed(clazz)
-    verify_static_utils(clazz)
-    # verify_overload_args(clazz)
-    verify_callback_handlers(clazz)
-    verify_context_first(clazz)
-    verify_listener_last(clazz)
-    verify_resource_names(clazz)
-    verify_files(clazz)
-    verify_manager_list(clazz)
-    verify_abstract_inner(clazz)
-    verify_runtime_exceptions(clazz)
-    verify_error(clazz)
-    verify_units(clazz)
-    verify_closable(clazz)
-    verify_member_name_not_kotlin_keyword(clazz)
-    verify_method_name_not_kotlin_operator(clazz)
-    verify_collections_over_arrays(clazz)
-    verify_user_handle(clazz)
-    verify_params(clazz)
-    verify_services(clazz)
-    verify_tense(clazz)
-    verify_icu(clazz)
-    verify_clone(clazz)
-    verify_pfd(clazz)
-    verify_numbers(clazz)
-    verify_singleton(clazz)
-    verify_nullability(clazz)
 
 
 def examine_stream(stream, base_stream=None, in_classes_with_base=[], out_classes_with_base=None):
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
index f34492d..5cb43db 100644
--- a/tools/apilint/apilint_test.py
+++ b/tools/apilint/apilint_test.py
@@ -242,6 +242,10 @@
         cls = self._cls("class Class {")
         return apilint.Field(cls, 1, raw, '', sig_format=2)
 
+    def test_parse_package(self):
+        pkg = apilint.Package(999, "package wifi.p2p {", None)
+        self.assertEquals("wifi.p2p", pkg.name)
+
     def test_class(self):
         cls = self._cls("@Deprecated @IntRange(from=1, to=2) public static abstract class Some.Name extends Super<Class> implements Interface<Class> {")
         self.assertTrue('deprecated' in cls.split)
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
index 6f58893..1ad7ada 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
 
@@ -86,20 +87,98 @@
     }
 
     /**
+     * Represents a way to access a property, either a getter or a field.
+     */
+    public static final class Accessor {
+        private final String mName;
+        private final Type mType;
+
+        /**
+         * Construct an accessor for a field.
+         *
+         * @param name The name of the field
+         * @return The new accessor
+         * @see Type#FIELD
+         */
+        static Accessor ofField(String name) {
+            return new Accessor(name, Type.FIELD);
+        }
+
+        /**
+         * Construct an accessor for a getter.
+         *
+         * @param name The name of the getter
+         * @return The new accessor
+         * @see Type#GETTER
+         */
+        static Accessor ofGetter(String name) {
+            return new Accessor(name, Type.GETTER);
+        }
+
+        public Accessor(String name, Type type) {
+            mName = Objects.requireNonNull(name, "Accessor name must not be null");
+            mType = Objects.requireNonNull(type, "Accessor type must not be null");
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public Type getType() {
+            return mType;
+        }
+
+        /**
+         * Get the invocation of this accessor.
+         *
+         * Example: {@code "getValue()"} for a getter or {@code "valueField"} for a field.
+         *
+         * @return A string representing the invocation of this accessor
+         */
+        public String invocation() {
+            switch (mType) {
+                case FIELD:
+                    return mName;
+                case GETTER:
+                    return String.format("%s()", mName);
+                default:
+                    throw new NoSuchElementException(
+                            String.format("No such accessor type %s", mType));
+            }
+        }
+
+        public enum Type {
+            /**
+             * A property accessed by a public field.
+             *
+             * @see #ofField(String)
+             */
+            FIELD,
+
+            /**
+             * A property accessed by a public getter method.
+             *
+             * @see #ofGetter(String)
+             */
+            GETTER
+        }
+    }
+
+    /**
      * Model an inspectable property
      */
     public static final class Property {
         private final String mName;
-        private final String mGetter;
+        private final Accessor mAccessor;
         private final Type mType;
         private boolean mAttributeIdInferrableFromR = true;
         private int mAttributeId = 0;
         private List<IntEnumEntry> mIntEnumEntries;
         private List<IntFlagEntry> mIntFlagEntries;
 
-        public Property(String name, String getter, Type type) {
+        public Property(String name, Accessor accessor, Type type) {
             mName = Objects.requireNonNull(name, "Name must not be null");
-            mGetter = Objects.requireNonNull(getter, "Getter must not be null");
+            mAccessor = Objects.requireNonNull(accessor, "Accessor must not be null");
             mType = Objects.requireNonNull(type, "Type must not be null");
         }
 
@@ -129,8 +208,8 @@
             return mName;
         }
 
-        public String getGetter() {
-            return mGetter;
+        public Accessor getAccessor() {
+            return mAccessor;
         }
 
         public Type getType() {
@@ -229,7 +308,10 @@
              * @see android.view.inspector.IntFlagMapping
              * @see IntFlagEntry
              */
-            INT_FLAG
+            INT_FLAG,
+
+            /** A resource ID */
+            RESOURCE_ID
         }
     }
 
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 50c79da..20de90d 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
@@ -16,6 +16,7 @@
 
 package android.processor.view.inspector;
 
+import android.processor.view.inspector.InspectableClassModel.Accessor;
 import android.processor.view.inspector.InspectableClassModel.IntEnumEntry;
 import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
 import android.processor.view.inspector.InspectableClassModel.Property;
@@ -77,6 +78,54 @@
             "androidx.annotation.ColorLong"};
 
     /**
+     * Set of android and androidx annotation qualified names of resource ID annotations.
+     */
+    private static final String[] RESOURCE_ID_ANNOTATION_NAMES = {
+            "android.annotation.AnimatorRes",
+            "android.annotation.AnimRes",
+            "android.annotation.AnyRes",
+            "android.annotation.ArrayRes",
+            "android.annotation.BoolRes",
+            "android.annotation.DimenRes",
+            "android.annotation.DrawableRes",
+            "android.annotation.FontRes",
+            "android.annotation.IdRes",
+            "android.annotation.IntegerRes",
+            "android.annotation.InterpolatorRes",
+            "android.annotation.LayoutRes",
+            "android.annotation.MenuRes",
+            "android.annotation.NavigationRes",
+            "android.annotation.PluralsRes",
+            "android.annotation.RawRes",
+            "android.annotation.StringRes",
+            "android.annotation.StyleableRes",
+            "android.annotation.StyleRes",
+            "android.annotation.TransitionRes",
+            "android.annotation.XmlRes",
+            "androidx.annotation.AnimatorRes",
+            "androidx.annotation.AnimRes",
+            "androidx.annotation.AnyRes",
+            "androidx.annotation.ArrayRes",
+            "androidx.annotation.BoolRes",
+            "androidx.annotation.DimenRes",
+            "androidx.annotation.DrawableRes",
+            "androidx.annotation.FontRes",
+            "androidx.annotation.IdRes",
+            "androidx.annotation.IntegerRes",
+            "androidx.annotation.InterpolatorRes",
+            "androidx.annotation.LayoutRes",
+            "androidx.annotation.MenuRes",
+            "androidx.annotation.NavigationRes",
+            "androidx.annotation.PluralsRes",
+            "androidx.annotation.RawRes",
+            "androidx.annotation.StringRes",
+            "androidx.annotation.StyleableRes",
+            "androidx.annotation.StyleRes",
+            "androidx.annotation.TransitionRes",
+            "androidx.annotation.XmlRes"
+    };
+
+    /**
      * @param annotationQualifiedName The qualified name of the annotation to process
      * @param processingEnv           The processing environment from the parent processor
      */
@@ -93,16 +142,15 @@
         try {
             final AnnotationMirror annotation =
                     mAnnotationUtils.exactlyOneMirror(mQualifiedName, element);
-            final ExecutableElement getter = ensureGetter(element);
-            final Property property = buildProperty(getter, annotation);
+            final Property property = buildProperty(element, annotation);
 
             model.getProperty(property.getName()).ifPresent(p -> {
                 throw new ProcessingException(
                         String.format(
-                                "Property \"%s\" is already defined on #%s().",
+                                "Property \"%s\" is already defined on #%s.",
                                 p.getName(),
-                                p.getGetter()),
-                        getter,
+                                p.getAccessor().invocation()),
+                        element,
                         annotation);
             });
 
@@ -112,6 +160,95 @@
         }
     }
 
+
+    /**
+     * Build a {@link Property} from a getter and an inspectable property annotation.
+     *
+     * @param accessor An element representing the getter or public field to build from
+     * @param annotation A mirror of an inspectable property-shaped annotation
+     * @return A property for the getter and annotation
+     * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled
+     */
+    private Property buildProperty(Element accessor, AnnotationMirror annotation) {
+        final Property property;
+        final Optional<String> nameFromAnnotation = mAnnotationUtils
+                .typedValueByName("name", String.class, accessor, annotation);
+
+        validateModifiers(accessor);
+
+        switch (accessor.getKind()) {
+            case FIELD:
+                property = new Property(
+                        nameFromAnnotation.orElseGet(() -> accessor.getSimpleName().toString()),
+                        Accessor.ofField(accessor.getSimpleName().toString()),
+                        determinePropertyType(accessor, annotation));
+                break;
+            case METHOD:
+                final ExecutableElement getter = ensureGetter(accessor);
+
+                property = new Property(
+                        nameFromAnnotation.orElseGet(() -> inferPropertyNameFromGetter(getter)),
+                        Accessor.ofGetter(getter.getSimpleName().toString()),
+                        determinePropertyType(getter, annotation));
+                break;
+            default:
+                throw new ProcessingException(
+                        String.format(
+                                "Property must either be a getter method or a field, got %s.",
+                                accessor.getKind()
+                        ),
+                        accessor,
+                        annotation);
+        }
+
+        mAnnotationUtils
+                .typedValueByName("hasAttributeId", Boolean.class, accessor, annotation)
+                .ifPresent(property::setAttributeIdInferrableFromR);
+
+        mAnnotationUtils
+                .typedValueByName("attributeId", Integer.class, accessor, annotation)
+                .ifPresent(property::setAttributeId);
+
+        switch (property.getType()) {
+            case INT_ENUM:
+                property.setIntEnumEntries(processEnumMapping(accessor, annotation));
+                break;
+            case INT_FLAG:
+                property.setIntFlagEntries(processFlagMapping(accessor, annotation));
+                break;
+        }
+
+        return property;
+    }
+
+    /**
+     * Validates that an element is public, concrete, and non-static.
+     *
+     * @param element The element to check
+     * @throws ProcessingException If the element's modifiers are invalid
+     */
+    private void validateModifiers(Element element) {
+        final Set<Modifier> modifiers = element.getModifiers();
+
+        if (!modifiers.contains(Modifier.PUBLIC)) {
+            throw new ProcessingException(
+                    "Property getter methods and fields must be public.",
+                    element);
+        }
+
+        if (modifiers.contains(Modifier.ABSTRACT)) {
+            throw new ProcessingException(
+                    "Property getter methods must not be abstract.",
+                    element);
+        }
+
+        if (modifiers.contains(Modifier.STATIC)) {
+            throw new ProcessingException(
+                    "Property getter methods and fields must not be static.",
+                    element);
+        }
+    }
+
     /**
      * Check that an element is shaped like a getter.
      *
@@ -127,25 +264,7 @@
         }
 
         final ExecutableElement method = (ExecutableElement) element;
-        final Set<Modifier> modifiers = method.getModifiers();
 
-        if (modifiers.contains(Modifier.PRIVATE)) {
-            throw new ProcessingException(
-                    "Property getter methods must not be private.",
-                    element);
-        }
-
-        if (modifiers.contains(Modifier.ABSTRACT)) {
-            throw new ProcessingException(
-                    "Property getter methods must not be abstract.",
-                    element);
-        }
-
-        if (modifiers.contains(Modifier.STATIC)) {
-            throw new ProcessingException(
-                    "Property getter methods must not be static.",
-                    element);
-        }
 
         if (!method.getParameters().isEmpty()) {
             throw new ProcessingException(
@@ -171,77 +290,40 @@
         return method;
     }
 
-    /**
-     * Build a {@link Property} from a getter and an inspectable property annotation.
-     *
-     * @param getter     An element representing the getter to build from
-     * @param annotation A mirror of an inspectable property-shaped annotation
-     * @return A property for the getter and annotation
-     * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled
-     */
-    private Property buildProperty(ExecutableElement getter, AnnotationMirror annotation) {
-        final String name = mAnnotationUtils
-                .typedValueByName("name", String.class, getter, annotation)
-                .orElseGet(() -> inferPropertyNameFromGetter(getter));
-
-        final Property property = new Property(
-                name,
-                getter.getSimpleName().toString(),
-                determinePropertyType(getter, annotation));
-
-        mAnnotationUtils
-                .typedValueByName("hasAttributeId", Boolean.class, getter, annotation)
-                .ifPresent(property::setAttributeIdInferrableFromR);
-
-        mAnnotationUtils
-                .typedValueByName("attributeId", Integer.class, getter, annotation)
-                .ifPresent(property::setAttributeId);
-
-        switch (property.getType()) {
-            case INT_ENUM:
-                property.setIntEnumEntries(processEnumMapping(getter, annotation));
-                break;
-            case INT_FLAG:
-                property.setIntFlagEntries(processFlagMapping(getter, annotation));
-                break;
-        }
-
-        return property;
-    }
 
     /**
      * Determine the property type from the annotation, return type, or context clues.
      *
-     * @param getter     An element representing the getter to build from
+     * @param accessor An element representing the getter or field to determine the type of
      * @param annotation A mirror of an inspectable property-shaped annotation
      * @return The resolved property type
      * @throws ProcessingException If the property type cannot be resolved or is invalid
      * @see android.view.inspector.InspectableProperty#valueType()
      */
     private Property.Type determinePropertyType(
-            ExecutableElement getter,
+            Element accessor,
             AnnotationMirror annotation) {
 
         final String valueType = mAnnotationUtils
-                .untypedValueByName("valueType", getter, annotation)
+                .untypedValueByName("valueType", accessor, annotation)
                 .map(Object::toString)
                 .orElse("INFERRED");
 
-        final Property.Type returnType = convertReturnTypeToPropertyType(getter);
+        final Property.Type accessorType =
+                convertTypeMirrorToPropertyType(extractReturnOrFieldType(accessor), accessor);
 
-        final boolean hasColor = hasColorAnnotation(getter);
         final Optional<AnnotationValue> enumMapping =
                 mAnnotationUtils.valueByName("enumMapping", annotation);
         final Optional<AnnotationValue> flagMapping =
                 mAnnotationUtils.valueByName("flagMapping", annotation);
 
-        if (returnType != Property.Type.INT) {
+        if (accessorType != Property.Type.INT) {
             enumMapping.ifPresent(value -> {
                 throw new ProcessingException(
                         String.format(
                                 "Can only use enumMapping on int types, got %s.",
-                                returnType.toString().toLowerCase()),
-                        getter,
+                                accessorType.toString().toLowerCase()),
+                        accessor,
                         annotation,
                         value);
             });
@@ -249,36 +331,63 @@
                 throw new ProcessingException(
                         String.format(
                                 "Can only use flagMapping on int types, got %s.",
-                                returnType.toString().toLowerCase()),
-                        getter,
+                                accessorType.toString().toLowerCase()),
+                        accessor,
                         annotation,
                         value);
             });
         }
 
+
         switch (valueType) {
             case "INFERRED":
+                final boolean hasColor = hasColorAnnotation(accessor);
+                final boolean hasResourceId = hasResourceIdAnnotation(accessor);
+
                 if (hasColor) {
                     enumMapping.ifPresent(value -> {
                         throw new ProcessingException(
                                 "Cannot use enumMapping on a color type.",
-                                getter,
+                                accessor,
                                 annotation,
                                 value);
                     });
                     flagMapping.ifPresent(value -> {
                         throw new ProcessingException(
                                 "Cannot use flagMapping on a color type.",
-                                getter,
+                                accessor,
                                 annotation,
                                 value);
                     });
+                    if (hasResourceId) {
+                        throw new ProcessingException(
+                                "Cannot infer type, both color and resource ID annotations "
+                                        + "are present.",
+                                accessor,
+                                annotation);
+                    }
                     return Property.Type.COLOR;
+                } else if (hasResourceId) {
+                    enumMapping.ifPresent(value -> {
+                        throw new ProcessingException(
+                                "Cannot use enumMapping on a resource ID type.",
+                                accessor,
+                                annotation,
+                                value);
+                    });
+                    flagMapping.ifPresent(value -> {
+                        throw new ProcessingException(
+                                "Cannot use flagMapping on a resource ID type.",
+                                accessor,
+                                annotation,
+                                value);
+                    });
+                    return Property.Type.RESOURCE_ID;
                 } else if (enumMapping.isPresent()) {
                     flagMapping.ifPresent(value -> {
                         throw new ProcessingException(
                                 "Cannot use flagMapping and enumMapping simultaneously.",
-                                getter,
+                                accessor,
                                 annotation,
                                 value);
                     });
@@ -286,12 +395,12 @@
                 } else if (flagMapping.isPresent()) {
                     return Property.Type.INT_FLAG;
                 } else {
-                    return returnType;
+                    return accessorType;
                 }
             case "NONE":
-                return returnType;
+                return accessorType;
             case "COLOR":
-                switch (returnType) {
+                switch (accessorType) {
                     case COLOR:
                     case INT:
                     case LONG:
@@ -299,37 +408,60 @@
                     default:
                         throw new ProcessingException(
                                 "Color must be a long, integer, or android.graphics.Color",
-                                getter,
+                                accessor,
                                 annotation);
                 }
             case "GRAVITY":
-                requirePackedIntToReturnInt("Gravity", returnType, getter, annotation);
+                requirePackedIntToBeInt("Gravity", accessorType, accessor, annotation);
                 return Property.Type.GRAVITY;
             case "INT_ENUM":
-                requirePackedIntToReturnInt("IntEnum", returnType, getter, annotation);
+                requirePackedIntToBeInt("IntEnum", accessorType, accessor, annotation);
                 return Property.Type.INT_ENUM;
             case "INT_FLAG":
-                requirePackedIntToReturnInt("IntFlag", returnType, getter, annotation);
+                requirePackedIntToBeInt("IntFlag", accessorType, accessor, annotation);
                 return Property.Type.INT_FLAG;
+            case "RESOURCE_ID":
+                return Property.Type.RESOURCE_ID;
             default:
                 throw new ProcessingException(
                         String.format("Unknown value type enumeration value: %s", valueType),
-                        getter,
+                        accessor,
                         annotation);
         }
     }
 
     /**
-     * Get a property type from the return type of a getter.
+     * Get the type of a field or the return type of a method.
      *
-     * @param getter The getter to extract the return type of
+     * @param element The element to extract a {@link TypeMirror} from
+     * @return The return or field type of the element
+     * @throws ProcessingException If the element is not a field or a method
+     */
+    private TypeMirror extractReturnOrFieldType(Element element) {
+        switch (element.getKind()) {
+            case FIELD:
+                return element.asType();
+            case METHOD:
+                return ((ExecutableElement) element).getReturnType();
+            default:
+                throw new ProcessingException(
+                        String.format(
+                                "Unable to determine the type of a %s.",
+                                element.getKind()),
+                        element);
+        }
+    }
+
+    /**
+     * Get a property type from a type mirror
+     *
+     * @param typeMirror The type mirror to convert to a property type
+     * @param element The element to be used for exceptions
      * @return The property type returned by the getter
      * @throws ProcessingException If the return type is not a primitive or an object
      */
-    private Property.Type convertReturnTypeToPropertyType(ExecutableElement getter) {
-        final TypeMirror returnType = getter.getReturnType();
-
-        switch (unboxType(returnType)) {
+    private Property.Type convertTypeMirrorToPropertyType(TypeMirror typeMirror, Element element) {
+        switch (unboxType(typeMirror)) {
             case BOOLEAN:
                 return Property.Type.BOOLEAN;
             case BYTE:
@@ -347,7 +479,7 @@
             case SHORT:
                 return Property.Type.SHORT;
             case DECLARED:
-                if (isColorType(returnType)) {
+                if (isColorType(typeMirror)) {
                     return Property.Type.COLOR;
                 } else {
                     return Property.Type.OBJECT;
@@ -356,24 +488,24 @@
                 return Property.Type.OBJECT;
             default:
                 throw new ProcessingException(
-                        String.format("Unsupported return type %s.", returnType),
-                        getter);
+                        String.format("Unsupported property type %s.", typeMirror),
+                        element);
         }
     }
 
     /**
      * Require that a value type packed into an integer be on a getter that returns an int.
      *
-     * @param typeName   The name of the type to use in the exception
+     * @param typeName The name of the type to use in the exception
      * @param returnType The return type of the getter to check
-     * @param getter     The getter, to use in the exception
+     * @param accessor The getter, to use in the exception
      * @param annotation The annotation, to use in the exception
      * @throws ProcessingException If the return type is not an int
      */
-    private static void requirePackedIntToReturnInt(
+    private static void requirePackedIntToBeInt(
             String typeName,
             Property.Type returnType,
-            ExecutableElement getter,
+            Element accessor,
             AnnotationMirror annotation) {
         if (returnType != Property.Type.INT) {
             throw new ProcessingException(
@@ -381,7 +513,7 @@
                             "%s can only be defined on a method that returns int, got %s.",
                             typeName,
                             returnType.toString().toLowerCase()),
-                    getter,
+                    accessor,
                     annotation);
         }
     }
@@ -393,21 +525,21 @@
      * not considered to be annotated, nor is a {@code long} annotated with
      * {@link android.annotation.ColorInt}.
      *
-     * @param getter The getter to query
+     * @param accessor The getter or field to query
      * @return True if the getter has a color annotation, false otherwise
      */
-    private boolean hasColorAnnotation(ExecutableElement getter) {
-        switch (unboxType(getter.getReturnType())) {
+    private boolean hasColorAnnotation(Element accessor) {
+        switch (unboxType(extractReturnOrFieldType(accessor))) {
             case INT:
                 for (String name : COLOR_INT_ANNOTATION_NAMES) {
-                    if (mAnnotationUtils.hasAnnotation(getter, name)) {
+                    if (mAnnotationUtils.hasAnnotation(accessor, name)) {
                         return true;
                     }
                 }
                 return false;
             case LONG:
                 for (String name : COLOR_LONG_ANNOTATION_NAMES) {
-                    if (mAnnotationUtils.hasAnnotation(getter, name)) {
+                    if (mAnnotationUtils.hasAnnotation(accessor, name)) {
                         return true;
                     }
                 }
@@ -418,6 +550,24 @@
     }
 
     /**
+     * Determine if a getter or a field is annotated with a resource ID annotation.
+     *
+     * @param accessor The getter or field to query
+     * @return True if the accessor is an integer and has a resource ID annotation, false otherwise
+     */
+    private boolean hasResourceIdAnnotation(Element accessor) {
+        if (unboxType(extractReturnOrFieldType(accessor)) == TypeKind.INT) {
+            for (String name : RESOURCE_ID_ANNOTATION_NAMES) {
+                if (mAnnotationUtils.hasAnnotation(accessor, name)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Infer a property name from a getter method.
      *
      * If the method is prefixed with {@code get}, the prefix will be stripped, and the
@@ -452,40 +602,40 @@
      *
      * @see android.view.inspector.IntEnumMapping
      * @see android.view.inspector.InspectableProperty#enumMapping()
-     * @param getter The getter of the property, used for exceptions
+     * @param accessor The accessor of the property, used for exceptions
      * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to
      *                   extract enum mapping values from.
      * @return A list of int enum entries, in the order specified in source
      * @throws ProcessingException if mapping doesn't exist or is invalid
      */
     private List<IntEnumEntry> processEnumMapping(
-            ExecutableElement getter,
+            Element accessor,
             AnnotationMirror annotation) {
         List<AnnotationMirror> enumAnnotations = mAnnotationUtils.typedArrayValuesByName(
-                "enumMapping", AnnotationMirror.class, getter, annotation);
+                "enumMapping", AnnotationMirror.class, accessor, annotation);
         List<IntEnumEntry> enumEntries = new ArrayList<>(enumAnnotations.size());
 
         if (enumAnnotations.isEmpty()) {
             throw new ProcessingException(
-                    "Encountered an empty array for enumMapping", getter, annotation);
+                    "Encountered an empty array for enumMapping", accessor, annotation);
         }
 
         for (AnnotationMirror enumAnnotation : enumAnnotations) {
             final String name = mAnnotationUtils.typedValueByName(
-                    "name", String.class, getter, enumAnnotation)
+                    "name", String.class, accessor, enumAnnotation)
                     .orElseThrow(() -> {
                         throw new ProcessingException(
                                 "Name is required for @EnumMap",
-                                getter,
+                                accessor,
                                 enumAnnotation);
                     });
 
             final int value = mAnnotationUtils.typedValueByName(
-                    "value", Integer.class, getter, enumAnnotation)
+                    "value", Integer.class, accessor, enumAnnotation)
                     .orElseThrow(() -> {
                         throw new ProcessingException(
                                 "Value is required for @EnumMap",
-                                getter,
+                                accessor,
                                 enumAnnotation);
                     });
 
@@ -504,45 +654,45 @@
      *
      * @see android.view.inspector.IntFlagMapping
      * @see android.view.inspector.InspectableProperty#flagMapping()
-     * @param getter The getter of the property, used for exceptions
+     * @param accessor The accessor of the property, used for exceptions
      * @param annotation The {@link android.view.inspector.InspectableProperty} annotation to
      *                   extract flag mapping values from.
      * @return A list of int flags entries, in the order specified in source
      * @throws ProcessingException if mapping doesn't exist or is invalid
      */
     private List<IntFlagEntry> processFlagMapping(
-            ExecutableElement getter,
+            Element accessor,
             AnnotationMirror annotation) {
         List<AnnotationMirror> flagAnnotations = mAnnotationUtils.typedArrayValuesByName(
-                "flagMapping", AnnotationMirror.class, getter, annotation);
+                "flagMapping", AnnotationMirror.class, accessor, annotation);
         List<IntFlagEntry> flagEntries = new ArrayList<>(flagAnnotations.size());
 
         if (flagAnnotations.isEmpty()) {
             throw new ProcessingException(
-                    "Encountered an empty array for flagMapping", getter, annotation);
+                    "Encountered an empty array for flagMapping", accessor, annotation);
         }
 
         for (AnnotationMirror flagAnnotation : flagAnnotations) {
             final String name = mAnnotationUtils.typedValueByName(
-                    "name", String.class, getter, flagAnnotation)
+                    "name", String.class, accessor, flagAnnotation)
                     .orElseThrow(() -> {
                         throw new ProcessingException(
                                 "Name is required for @FlagMap",
-                                getter,
+                                accessor,
                                 flagAnnotation);
                     });
 
             final int target = mAnnotationUtils.typedValueByName(
-                    "target", Integer.class, getter, flagAnnotation)
+                    "target", Integer.class, accessor, flagAnnotation)
                     .orElseThrow(() -> {
                         throw new ProcessingException(
                                 "Target is required for @FlagMap",
-                                getter,
+                                accessor,
                                 flagAnnotation);
                     });
 
             final Optional<Integer> mask = mAnnotationUtils.typedValueByName(
-                    "mask", Integer.class, getter, flagAnnotation);
+                    "mask", Integer.class, accessor, flagAnnotation);
 
             if (mask.isPresent()) {
                 flagEntries.add(new IntFlagEntry(name, target, mask.get()));
diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
index 7b04645..44d88bb 100644
--- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
+++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java
@@ -16,6 +16,7 @@
 
 package android.processor.view.inspector;
 
+
 import android.processor.view.inspector.InspectableClassModel.IntEnumEntry;
 import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
 import android.processor.view.inspector.InspectableClassModel.Property;
@@ -268,10 +269,10 @@
 
         for (PropertyIdField propertyIdField : propertyIdFields) {
             builder.addStatement(
-                    "propertyReader.read$L($N, node.$L())",
+                    "propertyReader.read$L($N, node.$L)",
                     methodSuffixForPropertyType(propertyIdField.mProperty.getType()),
                     propertyIdField.mFieldSpec,
-                    propertyIdField.mProperty.getGetter());
+                    propertyIdField.mProperty.getAccessor().invocation());
         }
 
         return builder.build();
@@ -445,6 +446,8 @@
                 return "IntEnum";
             case INT_FLAG:
                 return "IntFlag";
+            case RESOURCE_ID:
+                return "ResourceId";
             default:
                 throw new NoSuchElementException(String.format("No such property type, %s", type));
         }
diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
index f6d8bb0..4eed504 100644
--- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
+++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java
@@ -20,6 +20,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
+
+import android.processor.view.inspector.InspectableClassModel.Accessor;
 import android.processor.view.inspector.InspectableClassModel.IntEnumEntry;
 import android.processor.view.inspector.InspectableClassModel.IntFlagEntry;
 import android.processor.view.inspector.InspectableClassModel.Property;
@@ -80,13 +82,14 @@
         addProperty("object", "getObject", Property.Type.OBJECT);
         addProperty("color", "getColor", Property.Type.COLOR);
         addProperty("gravity", "getGravity", Property.Type.GRAVITY);
+        addProperty("resourceId", "getResourceId", Property.Type.RESOURCE_ID);
 
         assertGeneratedFileEquals("SimpleProperties");
     }
 
     @Test
     public void testNoAttributeId() {
-        final Property property = new Property(
+        final Property property = addProperty(
                 "noAttributeProperty",
                 "getNoAttributeProperty",
                 Property.Type.INT);
@@ -98,19 +101,18 @@
 
     @Test
     public void testSuppliedAttributeId() {
-        final Property property = new Property(
+        final Property property = addProperty(
                 "suppliedAttributeProperty",
                 "getSuppliedAttributeProperty",
                 Property.Type.INT);
         property.setAttributeId(0xdecafbad);
-        mModel.putProperty(property);
 
         assertGeneratedFileEquals("SuppliedAttributeId");
     }
 
     @Test
     public void testIntEnum() {
-        final Property property = new Property(
+        final Property property = addProperty(
                 "intEnumProperty",
                 "getIntEnumProperty",
                 Property.Type.INT_ENUM);
@@ -127,7 +129,7 @@
 
     @Test
     public void testIntFlag() {
-        final Property property = new Property(
+        final Property property = addProperty(
                 "intFlag",
                 "getIntFlag",
                 Property.Type.INT_FLAG);
@@ -139,13 +141,21 @@
                 new IntFlagEntry("WARP", 0x4)
         ));
 
-        mModel.putProperty(property);
-
         assertGeneratedFileEquals("IntFlag");
     }
 
+    @Test
+    public void testFieldProperty() {
+        mModel.putProperty(new Property(
+                "fieldProperty",
+                Accessor.ofField("fieldProperty"),
+                Property.Type.INT));
+
+        assertGeneratedFileEquals("FieldProperty");
+    }
+
     private Property addProperty(String name, String getter, Property.Type type) {
-        final Property property = new Property(name, getter, type);
+        final Property property = new Property(name, Accessor.ofGetter(getter), type);
         mModel.putProperty(property);
         return property;
     }
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
new file mode 100644
index 0000000..a44c43e
--- /dev/null
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/FieldProperty.java.txt
@@ -0,0 +1,39 @@
+package com.android.node;
+
+import android.R;
+import android.view.inspector.InspectionCompanion;
+import android.view.inspector.PropertyMapper;
+import android.view.inspector.PropertyReader;
+import java.lang.Override;
+
+/**
+ * Inspection companion for {@link TestNode}.
+ *
+ * Generated by {@link android.processor.view.inspector.InspectionCompanionGenerator}
+ * on behalf of {@link android.processor.view.inspector.InspectionCompanionGeneratorTest}.
+ */
+public final class TestNode$$InspectionCompanion implements InspectionCompanion<TestNode> {
+    /**
+     * Set by {@link #mapProperties(PropertyMapper)} once properties have been mapped.
+     */
+    private boolean mPropertiesMapped = false;
+
+    /**
+     * Property ID of {@code fieldProperty}.
+     */
+    private int mFieldPropertyId;
+
+    @Override
+    public void mapProperties(PropertyMapper propertyMapper) {
+        mFieldPropertyId = propertyMapper.mapInt("fieldProperty", R.attr.fieldProperty);
+        mPropertiesMapped = true;
+    }
+
+    @Override
+    public void readProperties(TestNode node, PropertyReader propertyReader) {
+        if (!mPropertiesMapped) {
+            throw new InspectionCompanion.UninitializedPropertyMapException();
+        }
+        propertyReader.readInt(mFieldPropertyId, node.fieldProperty);
+    }
+}
diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
index dfc1bce..556d8dd 100644
--- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
+++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/SimpleProperties.java.txt
@@ -69,6 +69,11 @@
     private int mObjectId;
 
     /**
+     * Property ID of {@code resourceId}.
+     */
+    private int mResourceIdId;
+
+    /**
      * Property ID of {@code short}.
      */
     private int mShortId;
@@ -85,6 +90,7 @@
         mIntId = propertyMapper.mapInt("int", R.attr.int);
         mLongId = propertyMapper.mapLong("long", R.attr.long);
         mObjectId = propertyMapper.mapObject("object", R.attr.object);
+        mResourceIdId = propertyMapper.mapResourceId("resourceId", R.attr.resourceId);
         mShortId = propertyMapper.mapShort("short", R.attr.short);
         mPropertiesMapped = true;
     }
@@ -104,6 +110,7 @@
         propertyReader.readInt(mIntId, node.getInt());
         propertyReader.readLong(mLongId, node.getLong());
         propertyReader.readObject(mObjectId, node.getObject());
+        propertyReader.readResourceId(mResourceIdId, node.getResourceId());
         propertyReader.readShort(mShortId, node.getShort());
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index c59ad65..379819d 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -561,41 +561,48 @@
      * See {@link KeyMgmt} for descriptions of the values.
      * Defaults to WPA-PSK WPA-EAP.
      */
+    @NonNull
     public BitSet allowedKeyManagement;
     /**
      * The set of security protocols supported by this configuration.
      * See {@link Protocol} for descriptions of the values.
      * Defaults to WPA RSN.
      */
+    @NonNull
     public BitSet allowedProtocols;
     /**
      * The set of authentication protocols supported by this configuration.
      * See {@link AuthAlgorithm} for descriptions of the values.
      * Defaults to automatic selection.
      */
+    @NonNull
     public BitSet allowedAuthAlgorithms;
     /**
      * The set of pairwise ciphers for WPA supported by this configuration.
      * See {@link PairwiseCipher} for descriptions of the values.
      * Defaults to CCMP TKIP.
      */
+    @NonNull
     public BitSet allowedPairwiseCiphers;
     /**
      * The set of group ciphers supported by this configuration.
      * See {@link GroupCipher} for descriptions of the values.
      * Defaults to CCMP TKIP WEP104 WEP40.
      */
+    @NonNull
     public BitSet allowedGroupCiphers;
     /**
      * The set of group management ciphers supported by this configuration.
      * See {@link GroupMgmtCipher} for descriptions of the values.
      */
+    @NonNull
     public BitSet allowedGroupManagementCiphers;
     /**
      * The set of SuiteB ciphers supported by this configuration.
      * To be used for WPA3-Enterprise mode.
      * See {@link SuiteBCipher} for descriptions of the values.
      */
+    @NonNull
     public BitSet allowedSuiteBCiphers;
     /**
      * The enterprise configuration details specifying the EAP method,
@@ -2080,7 +2087,7 @@
      * @hide
      */
     public String getKeyIdForCredentials(WifiConfiguration current) {
-        String keyMgmt = null;
+        String keyMgmt = "";
 
         try {
             // Get current config details for fields that are not initialized
@@ -2089,14 +2096,17 @@
                 allowedKeyManagement = current.allowedKeyManagement;
             }
             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
-                keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
+                keyMgmt += KeyMgmt.strings[KeyMgmt.WPA_EAP];
             }
             if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
-                keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN];
+                keyMgmt += KeyMgmt.strings[KeyMgmt.OSEN];
             }
             if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
                 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
             }
+            if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+                keyMgmt += KeyMgmt.strings[KeyMgmt.SUITE_B_192];
+            }
 
             if (TextUtils.isEmpty(keyMgmt)) {
                 throw new IllegalStateException("Not an EAP network");
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8ef976f..6dd838c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4346,7 +4346,9 @@
 
     /**
      * Start subscription provisioning flow
+     *
      * @param provider {@link OsuProvider} to provision with
+     * @param executor the Executor on which to run the callback.
      * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow
      * @hide
      */
@@ -4355,45 +4357,48 @@
             android.Manifest.permission.NETWORK_SETTINGS,
             android.Manifest.permission.NETWORK_SETUP_WIZARD
     })
-    public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback,
-            @Nullable Handler handler) {
-        Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
+    public void startSubscriptionProvisioning(@NonNull OsuProvider provider,
+            @NonNull @CallbackExecutor Executor executor, @NonNull ProvisioningCallback callback) {
+        // Verify arguments
+        if (executor == null) {
+            throw new IllegalArgumentException("executor must not be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
         try {
             mService.startSubscriptionProvisioning(provider,
-                    new ProvisioningCallbackProxy(looper, callback));
+                    new ProvisioningCallbackProxy(executor, callback));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /**
+     * Helper class to support OSU Provisioning callbacks
+     */
     private static class ProvisioningCallbackProxy extends IProvisioningCallback.Stub {
-        private final Handler mHandler;
+        private final Executor mExecutor;
         private final ProvisioningCallback mCallback;
 
-        ProvisioningCallbackProxy(Looper looper, ProvisioningCallback callback) {
-            mHandler = new Handler(looper);
+        ProvisioningCallbackProxy(Executor executor, ProvisioningCallback callback) {
+            mExecutor = executor;
             mCallback = callback;
         }
 
         @Override
         public void onProvisioningStatus(int status) {
-            mHandler.post(() -> {
-                mCallback.onProvisioningStatus(status);
-            });
+            mExecutor.execute(() -> mCallback.onProvisioningStatus(status));
         }
 
         @Override
         public void onProvisioningFailure(int status) {
-            mHandler.post(() -> {
-                mCallback.onProvisioningFailure(status);
-            });
+            mExecutor.execute(() -> mCallback.onProvisioningFailure(status));
         }
 
         @Override
         public void onProvisioningComplete() {
-            mHandler.post(() -> {
-                mCallback.onProvisioningComplete();
-            });
+            mExecutor.execute(() -> mCallback.onProvisioningComplete());
         }
     }
 
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 8aef7a2..1a5cd5a 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -824,7 +824,7 @@
      * {@link NetworkSpecifierBuilder#setPeerHandle(PeerHandle)} to specify the peer to which the
      * connection is created.
      */
-    public static class NetworkSpecifierBuilder {
+    public static final class NetworkSpecifierBuilder {
         private DiscoverySession mDiscoverySession;
         private PeerHandle mPeerHandle;
         private String mPskPassphrase;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 5e1f569..6c1b073 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -17,6 +17,8 @@
 package android.net.wifi.p2p;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.net.MacAddress;
 import android.net.wifi.WpsInfo;
@@ -76,13 +78,19 @@
         GROUP_OWNER_BAND_5GHZ
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface GroupOwnerBandType {}
+    public @interface GroupOperatingBandType {}
 
     /**
-     * Recognized Group Owner required band.
+     * Allow the system to pick the operating frequency from all supported bands.
      */
     public static final int GROUP_OWNER_BAND_AUTO = 0;
+    /**
+     * Allow the system to pick the operating frequency from the 2.4 GHz band.
+     */
     public static final int GROUP_OWNER_BAND_2GHZ = 1;
+    /**
+     * Allow the system to pick the operating frequency from the 5 GHz band.
+     */
     public static final int GROUP_OWNER_BAND_5GHZ = 2;
 
     /**
@@ -240,7 +248,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setDeviceAddress(MacAddress deviceAddress) {
+        public @NonNull Builder setDeviceAddress(@Nullable MacAddress deviceAddress) {
             if (deviceAddress == null) {
                 mDeviceAddress = MAC_ANY_ADDRESS;
             } else {
@@ -255,7 +263,9 @@
          * <p>
          * A network name shall begin with "DIRECT-xy". x and y are selected
          * from the following character set: upper case letters, lower case
-         * letters and numbers.
+         * letters and numbers. Any byte values allowed for an SSID according to
+         * IEEE802.11-2012 [1] may be included after the string "DIRECT-xy"
+         * (including none).
          * <p>
          *     Must be called - an empty network name or an network name
          *     not conforming to the P2P Group ID naming rule is not valid.
@@ -264,7 +274,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setNetworkName(String networkName) {
+        public @NonNull Builder setNetworkName(@NonNull String networkName) {
             if (TextUtils.isEmpty(networkName)) {
                 throw new IllegalArgumentException(
                         "network name must be non-empty.");
@@ -284,17 +294,24 @@
         /**
          * Specify the passphrase for creating or joining a group.
          * <p>
+         * The passphrase must be an ASCII string whose length is between 8
+         * and 63.
+         * <p>
          *     Must be called - an empty passphrase is not valid.
          *
          * @param passphrase the passphrase of a group.
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setPassphrase(String passphrase) {
+        public @NonNull Builder setPassphrase(@NonNull String passphrase) {
             if (TextUtils.isEmpty(passphrase)) {
                 throw new IllegalArgumentException(
                         "passphrase must be non-empty.");
             }
+            if (passphrase.length() < 8 || passphrase.length() > 63) {
+                throw new IllegalArgumentException(
+                        "The length of a passphrase must be between 8 and 63.");
+            }
             mPassphrase = passphrase;
             return this;
         }
@@ -331,7 +348,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setGroupOperatingBand(@GroupOwnerBandType int band) {
+        public @NonNull Builder setGroupOperatingBand(@GroupOperatingBandType int band) {
             switch (band) {
                 case GROUP_OWNER_BAND_AUTO:
                 case GROUP_OWNER_BAND_2GHZ:
@@ -346,7 +363,7 @@
         }
 
         /**
-         * Specify the frequency to use for creating the group or joining the group.
+         * Specify the frequency, in MHz, to use for creating the group or joining the group.
          * <p>
          * When creating a group as Group Owner using {@link WifiP2pManager#createGroup(
          * WifiP2pManager.Channel, WifiP2pConfig, WifiP2pManager.ActionListener)},
@@ -372,7 +389,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder setGroupOperatingFrequency(int frequency) {
+        public @NonNull Builder setGroupOperatingFrequency(int frequency) {
             if (frequency < 0) {
                 throw new IllegalArgumentException(
                     "Invalid group operating frequency!");
@@ -391,7 +408,7 @@
          * @return The builder to facilitate chaining
          *         {@code builder.setXXX(..).setXXX(..)}.
          */
-        public Builder enablePersistentMode(boolean persistent) {
+        public @NonNull Builder enablePersistentMode(boolean persistent) {
             if (persistent) {
                 mNetId = WifiP2pGroup.PERSISTENT_NET_ID;
             } else {
@@ -404,7 +421,7 @@
          * Build {@link WifiP2pConfig} given the current requests made on the builder.
          * @return {@link WifiP2pConfig} constructed based on builder method calls.
          */
-        public WifiP2pConfig build() {
+        public @NonNull WifiP2pConfig build() {
             if (TextUtils.isEmpty(mNetworkName)) {
                 throw new IllegalStateException(
                         "network name must be non-empty.");
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 63f47e7..29a18d2 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -816,7 +816,7 @@
          * The requested {@link android.net.wifi.p2p.WifiP2pDevice} is available.
          * @param wifiP2pDevice Wi-Fi p2p {@link android.net.wifi.p2p.WifiP2pDevice}
          */
-        void onDeviceInfoAvailable(WifiP2pDevice wifiP2pDevice);
+        void onDeviceInfoAvailable(@Nullable WifiP2pDevice wifiP2pDevice);
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/rtt/CivicLocation.java b/wifi/java/android/net/wifi/rtt/CivicLocation.java
index b438a69..1d41177 100644
--- a/wifi/java/android/net/wifi/rtt/CivicLocation.java
+++ b/wifi/java/android/net/wifi/rtt/CivicLocation.java
@@ -155,6 +155,16 @@
     }
 
     /**
+     * Converts a CivicLocation object to a SparseArray.
+     *
+     * @return the SparseArray<string> representation of the CivicLocation
+     */
+    @Nullable
+    public SparseArray<String> toSparseArray() {
+        return mCivicAddressElements;
+    }
+
+    /**
      * Generates a comma separated string of all the defined elements.
      *
      * @return a compiled string representing all elements
diff --git a/wifi/java/android/net/wifi/rtt/CivicLocationKeys.java b/wifi/java/android/net/wifi/rtt/CivicLocationKeys.java
index 17c3671..b03f4a9 100644
--- a/wifi/java/android/net/wifi/rtt/CivicLocationKeys.java
+++ b/wifi/java/android/net/wifi/rtt/CivicLocationKeys.java
@@ -25,9 +25,8 @@
 /**
  * Civic Address key types used to define address elements.
  *
- * <p>These keys can be used in ResponderLocation look-up the corresponding string values.</p>
- *
- * @hide
+ * <p>These keys can be used with {@code ResponderLocation.toCivicLocationSparseArray()}
+ * to look-up the corresponding string values.</p>
  */
 public class CivicLocationKeys {
 
@@ -69,7 +68,7 @@
     public static final int HNO = 19;
     /** House number suffix key e.g. A, 1/2. */
     public static final int HNS = 20;
-    /** Landmark or vanity address key e.g. Columbia Univ. */
+    /** Landmark or vanity address key e.g. Golden Gate Bridge. */
     public static final int LMK = 21;
     /** Additional Location info key e.g. South Wing. */
     public static final int LOC = 22;
@@ -77,7 +76,7 @@
     public static final int NAM = 23;
     /** Postal or ZIP code key e.g. 10027-1234. */
     public static final int POSTAL_CODE = 24;
-    /** Building key e.g. Low Library. */
+    /** Building key e.g. Lincoln Library. */
     public static final int BUILDING = 25;
     /** Apartment or suite key e.g. Apt 42. */
     public static final int APT = 26;
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 7c29ff4..a065bbc 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -245,8 +245,10 @@
     }
 
     /**
-     * @return The responder location represented as {@link ResponderLocation} which captures
-     * location information the responder is programmed to broadcast.
+     * @return The unverified responder location represented as {@link ResponderLocation} which
+     * captures location information the responder is programmed to broadcast. The responder
+     * location is referred to as unverified, because we are relying on the device/site
+     * administrator to correctly configure its location data.
      * <p>
      * Will return a {@code null} when the location information cannot be parsed.
      * <p>
@@ -254,10 +256,11 @@
      * exception.
      */
     @Nullable
-    public ResponderLocation getResponderLocation() {
+    public ResponderLocation getUnverifiedResponderLocation() {
         if (mStatus != STATUS_SUCCESS) {
             throw new IllegalStateException(
-                    "getResponderLocation(): invoked on an invalid result: getStatus()=" + mStatus);
+                    "getUnverifiedResponderLocation(): invoked on an invalid result: getStatus()="
+                            + mStatus);
         }
         return mResponderLocation;
     }
diff --git a/wifi/java/android/net/wifi/rtt/ResponderLocation.java b/wifi/java/android/net/wifi/rtt/ResponderLocation.java
index 7b25eed..37d5f0a 100644
--- a/wifi/java/android/net/wifi/rtt/ResponderLocation.java
+++ b/wifi/java/android/net/wifi/rtt/ResponderLocation.java
@@ -19,19 +19,25 @@
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.location.Address;
+import android.location.Location;
 import android.net.MacAddress;
+import android.net.Uri;
 import android.net.wifi.rtt.CivicLocationKeys.CivicLocationKeysType;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.SparseArray;
+import android.webkit.MimeTypeMap;
 
 import java.lang.annotation.Retention;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -151,24 +157,8 @@
     /** Version of the LCI protocol is 1.0, the only defined protocol at this time. */
     public static final int LCI_VERSION_1 = 1;
 
-    /**
-     * Enumerates the flags contained in getLciFlags()
-     *
-     * @hide
-     */
-    @Retention(SOURCE)
-    @IntDef(flag = true, value = {LCI_FLAGS_MASK_REGLOC_AGREEMENT, LCI_FLAGS_MASK_REGLOC_DSE,
-        LCI_FLAGS_MASK_DEPENDENT_STA, LCI_FLAGS_MASK_VERSION})
-    public @interface LciFlagMasks {
-    }
-    /** Location agreement flag is obtained by ANDing this mask with the getLciFlags() value.*/
-    public static final int LCI_FLAGS_MASK_REGLOC_AGREEMENT = 0x10;
-    /** Location DSE flag is obtained by ANDing this mask with the getLciFlags() value.*/
-    public static final int LCI_FLAGS_MASK_REGLOC_DSE = 0x08;
-    /** Dependent station flag is obtained by ANDing this mask with the getLciFlags() value. */
-    public static final int LCI_FLAGS_MASK_DEPENDENT_STA = 0x04;
-    /** Version bits are obtained by ANDing this mask with the getLciFlags() value.*/
-    public static final int LCI_FLAGS_MASK_VERSION = 0x03;
+    /** Provider/Source of the location */
+    private static final String LOCATION_PROVIDER = "WiFi Access Point";
 
     // LCI Subelement Z constants
     private static final int[] SUBELEMENT_Z_BIT_FIELD_LENGTHS = {2, 14, 24, 8};
@@ -178,9 +168,9 @@
 
     // LCI Subelement Z fields indices
     private static final int SUBELEMENT_Z_LAT_EXPECTED_TO_MOVE_INDEX = 0;
-    private static final int SUBELEMENT_Z_STA_FLOOR_NUMBER_INDEX = 1;
-    private static final int SUBELEMENT_Z_STA_HEIGHT_ABOVE_FLOOR_INDEX = 2;
-    private static final int SUBELEMENT_Z_STA_HEIGHT_ABOVE_FLOOR_UNCERTAINTY_INDEX = 3;
+    private static final int SUBELEMENT_Z_FLOOR_NUMBER_INDEX = 1;
+    private static final int SUBELEMENT_Z_HEIGHT_ABOVE_FLOOR_INDEX = 2;
+    private static final int SUBELEMENT_Z_HEIGHT_ABOVE_FLOOR_UNCERTAINTY_INDEX = 3;
 
     // LCI Subelement Usage Rules constants
     private static final int SUBELEMENT_USAGE_MASK_RETRANSMIT = 0x01;
@@ -233,72 +223,27 @@
 
     // LCR Map Image Subelement field indexes.
     private static final int SUBELEMENT_IMAGE_MAP_TYPE_INDEX = 0;
-
-    /**
-     * The Map Type value specifies the image format type.
-     *
-     * @hide
-     */
-    @Retention(SOURCE)
-    @IntDef({
-            MAP_TYPE_URL_DEFINED,
-            MAP_TYPE_PNG,
-            MAP_TYPE_GIF,
-            MAP_TYPE_JPG,
-            MAP_TYPE_SVG,
-            MAP_TYPE_DXF,
-            MAP_TYPE_DWG,
-            MAP_TYPE_DWF,
-            MAP_TYPE_CAD,
-            MAP_TYPE_TIFF,
-            MAP_TYPE_GML,
-            MAP_TYPE_KML,
-            MAP_TYPE_BMP,
-            MAP_TYPE_PGM,
-            MAP_TYPE_PPM,
-            MAP_TYPE_XBM,
-            MAP_TYPE_XPM,
-            MAP_TYPE_ICO
-    })
-    public @interface MapImageType {
-    }
-
-    /** File type defined by the file suffix itself. */
-    public static final int MAP_TYPE_URL_DEFINED = 0;
-    /** File type is in PNG format. */
-    public static final int MAP_TYPE_PNG = 1;
-    /** File type is in GIF format. */
-    public static final int MAP_TYPE_GIF = 2;
-    /** File type is in JPG format. */
-    public static final int MAP_TYPE_JPG = 3;
-    /** File type is in SVG format. */
-    public static final int MAP_TYPE_SVG = 4;
-    /** File type is in DXF format. */
-    public static final int MAP_TYPE_DXF = 5;
-    /** File type is in DWG format. */
-    public static final int MAP_TYPE_DWG = 6;
-    /** File type is in DWF format. */
-    public static final int MAP_TYPE_DWF = 7;
-    /** File type is in CAD format. */
-    public static final int MAP_TYPE_CAD = 8;
-    /** File type is in TIFF format. */
-    public static final int MAP_TYPE_TIFF = 9;
-    /** File type is in GML format. */
-    public static final int MAP_TYPE_GML = 10;
-    /** File type is in KML format. */
-    public static final int MAP_TYPE_KML = 11;
-    /** File type is in BMP format. */
-    public static final int MAP_TYPE_BMP = 12;
-    /** File type is in PGM format. */
-    public static final int MAP_TYPE_PGM = 13;
-    /** File type is in PPM format. */
-    public static final int MAP_TYPE_PPM = 14;
-    /** File type is in XBM format. */
-    public static final int MAP_TYPE_XBM = 15;
-    /** File type is in XPM format. */
-    public static final int MAP_TYPE_XPM = 16;
-    /** File type is in ICO format. */
-    public static final int MAP_TYPE_ICO = 17;
+    private static final int MAP_TYPE_URL_DEFINED = 0;
+    private static final String[] SUPPORTED_IMAGE_FILE_EXTENSIONS = {
+            "",
+            "png",
+            "gif",
+            "jpg",
+            "svg",
+            "dxf",
+            "dwg",
+            "dwf",
+            "cad",
+            "tif",
+            "gml",
+            "kml",
+            "bmp",
+            "pgm",
+            "ppm",
+            "xbm",
+            "xpm",
+            "ico"
+    };
 
     // General LCI and LCR state
     private final boolean mIsValid;
@@ -323,13 +268,16 @@
     private double mAltitudeUncertainty;
     private double mAltitude;
     private int mDatum;
-    private int mLciFlags;
+    private boolean mLciRegisteredLocationAgreement;
+    private boolean mLciRegisteredLocationDse;
+    private boolean mLciDependentStation;
+    private int mLciVersion;
 
     // LCI Subelement Z state
     private int mExpectedToMove;
-    private double mStaFloorNumber;
-    private double mStaHeightAboveFloorMeters;
-    private double mStaHeightAboveFloorUncertaintyMeters;
+    private double mFloorNumber;
+    private double mHeightAboveFloorMeters;
+    private double mHeightAboveFloorUncertaintyMeters;
 
     // LCI Subelement Usage Rights state
     private boolean mUsageRetransmit;
@@ -346,7 +294,7 @@
 
     // LCR Subelement Map Image state
     private int mMapImageType;
-    private URL mMapImageUrl;
+    private Uri mMapImageUri;
 
     /**
      * Constructor
@@ -360,7 +308,7 @@
         boolean isLciIeValid = false;
         boolean isLcrIeValid = false;
         setLciSubelementDefaults();
-        setZSubelementDefaults();
+        setZaxisSubelementDefaults();
         setUsageSubelementDefaults();
         setBssidListSubelementDefaults();
         setCivicLocationSubelementDefaults();
@@ -384,7 +332,7 @@
 
         if (!mIsValid) {
             setLciSubelementDefaults();
-            setZSubelementDefaults();
+            setZaxisSubelementDefaults();
             setCivicLocationSubelementDefaults();
             setMapImageSubelementDefaults();
         }
@@ -409,13 +357,16 @@
         mAltitudeUncertainty = in.readDouble();
         mAltitude = in.readDouble();
         mDatum = in.readInt();
-        mLciFlags = in.readInt();
+        mLciRegisteredLocationAgreement = in.readByte() != 0;
+        mLciRegisteredLocationDse = in.readByte() != 0;
+        mLciDependentStation = in.readByte() != 0;
+        mLciVersion = in.readInt();
 
         // LCI Subelement Z state
         mExpectedToMove = in.readInt();
-        mStaFloorNumber = in.readDouble();
-        mStaHeightAboveFloorMeters = in.readDouble();
-        mStaHeightAboveFloorUncertaintyMeters = in.readDouble();
+        mFloorNumber = in.readDouble();
+        mHeightAboveFloorMeters = in.readDouble();
+        mHeightAboveFloorUncertaintyMeters = in.readDouble();
 
         // LCI Usage Rights
         mUsageRetransmit = in.readByte() != 0;
@@ -432,10 +383,11 @@
 
         // LCR Subelement Map Image
         mMapImageType = in.readInt();
-        try {
-            mMapImageUrl = new URL(in.readString());
-        } catch (MalformedURLException e) {
-            mMapImageUrl = null;
+        String urlString = in.readString();
+        if (TextUtils.isEmpty(urlString)) {
+            mMapImageUri = null;
+        } else {
+            mMapImageUri = Uri.parse(urlString);
         }
     }
 
@@ -476,13 +428,16 @@
         parcel.writeDouble(mAltitudeUncertainty);
         parcel.writeDouble(mAltitude);
         parcel.writeInt(mDatum);
-        parcel.writeInt(mLciFlags);
+        parcel.writeByte((byte) (mLciRegisteredLocationAgreement ? 1 : 0));
+        parcel.writeByte((byte) (mLciRegisteredLocationDse ? 1 : 0));
+        parcel.writeByte((byte) (mLciDependentStation ? 1 : 0));
+        parcel.writeInt(mLciVersion);
 
         // LCI Subelement Z state
         parcel.writeInt(mExpectedToMove);
-        parcel.writeDouble(mStaFloorNumber);
-        parcel.writeDouble(mStaHeightAboveFloorMeters);
-        parcel.writeDouble(mStaHeightAboveFloorUncertaintyMeters);
+        parcel.writeDouble(mFloorNumber);
+        parcel.writeDouble(mHeightAboveFloorMeters);
+        parcel.writeDouble(mHeightAboveFloorUncertaintyMeters);
 
         // LCI Usage Rights
         parcel.writeByte((byte) (mUsageRetransmit ? 1 : 0));
@@ -499,8 +454,8 @@
 
         // LCR Subelement Map Image
         parcel.writeInt(mMapImageType);
-        if (mMapImageUrl != null) {
-            parcel.writeString(mMapImageUrl.toString());
+        if (mMapImageUri != null) {
+            parcel.writeString(mMapImageUri.toString());
         } else {
             parcel.writeString("");
         }
@@ -546,14 +501,14 @@
                 switch (subelement) {
                     case SUBELEMENT_LCI:
                         mIsLciValid = parseSubelementLci(subelementData);
-                        if (!mIsLciValid || (mLciFlags & LCI_FLAGS_MASK_VERSION) != LCI_VERSION_1) {
+                        if (!mIsLciValid || mLciVersion != LCI_VERSION_1) {
                             setLciSubelementDefaults();
                         }
                         break;
                     case SUBELEMENT_Z:
                         mIsZValid = parseSubelementZ(subelementData);
                         if (!mIsZValid) {
-                            setZSubelementDefaults();
+                            setZaxisSubelementDefaults();
                         }
                         break;
                     case SUBELEMENT_USAGE:
@@ -625,14 +580,13 @@
         mAltitude =
                 Math.scalb(subelementLciFields[SUBELEMENT_LCI_ALT_INDEX], -ALTITUDE_FRACTION_BITS);
         mDatum = (int) subelementLciFields[SUBELEMENT_LCI_DATUM_INDEX] & BYTE_MASK;
-        mLciFlags =
-                (int) subelementLciFields[SUBELEMENT_LCI_REGLOC_AGREEMENT_INDEX]
-                        * LCI_FLAGS_MASK_REGLOC_AGREEMENT
-                        | (int) subelementLciFields[SUBELEMENT_LCI_REGLOC_DSE_INDEX]
-                        * LCI_FLAGS_MASK_REGLOC_DSE
-                        | (int) subelementLciFields[SUBELEMENT_LCI_DEPENDENT_STA_INDEX]
-                        * LCI_FLAGS_MASK_DEPENDENT_STA
-                        | (int) subelementLciFields[SUBELEMENT_LCI_VERSION_INDEX];
+        mLciRegisteredLocationAgreement =
+                (subelementLciFields[SUBELEMENT_LCI_REGLOC_AGREEMENT_INDEX] == 1);
+        mLciRegisteredLocationDse =
+                (subelementLciFields[SUBELEMENT_LCI_REGLOC_DSE_INDEX] == 1);
+        mLciDependentStation =
+                (subelementLciFields[SUBELEMENT_LCI_DEPENDENT_STA_INDEX] == 1);
+        mLciVersion = (int) subelementLciFields[SUBELEMENT_LCI_VERSION_INDEX];
         return true;
     }
 
@@ -703,19 +657,18 @@
 
         mExpectedToMove =
                 (int) subelementZFields[SUBELEMENT_Z_LAT_EXPECTED_TO_MOVE_INDEX] & BYTE_MASK;
-
-        mStaFloorNumber = decodeZUnsignedToSignedValue(subelementZFields,
-                SUBELEMENT_Z_BIT_FIELD_LENGTHS, SUBELEMENT_Z_STA_FLOOR_NUMBER_INDEX,
+        mFloorNumber = decodeZUnsignedToSignedValue(subelementZFields,
+                SUBELEMENT_Z_BIT_FIELD_LENGTHS, SUBELEMENT_Z_FLOOR_NUMBER_INDEX,
                 Z_FLOOR_NUMBER_FRACTION_BITS);
 
-        mStaHeightAboveFloorMeters = decodeZUnsignedToSignedValue(subelementZFields,
-                SUBELEMENT_Z_BIT_FIELD_LENGTHS, SUBELEMENT_Z_STA_HEIGHT_ABOVE_FLOOR_INDEX,
+        mHeightAboveFloorMeters = decodeZUnsignedToSignedValue(subelementZFields,
+                SUBELEMENT_Z_BIT_FIELD_LENGTHS, SUBELEMENT_Z_HEIGHT_ABOVE_FLOOR_INDEX,
                 Z_FLOOR_HEIGHT_FRACTION_BITS);
 
         long zHeightUncertainty =
-                subelementZFields[SUBELEMENT_Z_STA_HEIGHT_ABOVE_FLOOR_UNCERTAINTY_INDEX];
+                subelementZFields[SUBELEMENT_Z_HEIGHT_ABOVE_FLOOR_UNCERTAINTY_INDEX];
         if (zHeightUncertainty > 0 && zHeightUncertainty < Z_MAX_HEIGHT_UNCERTAINTY_FACTOR) {
-            mStaHeightAboveFloorUncertaintyMeters =
+            mHeightAboveFloorUncertaintyMeters =
                     Math.pow(2, Z_FLOOR_HEIGHT_FRACTION_BITS - zHeightUncertainty - 1);
         } else {
             return false;
@@ -831,21 +784,38 @@
             return false;
         }
         int mapImageType = buffer[SUBELEMENT_IMAGE_MAP_TYPE_INDEX];
-        if (mapImageType < MAP_TYPE_URL_DEFINED || mapImageType > MAP_TYPE_DWG) {
+        int supportedTypesMax = SUPPORTED_IMAGE_FILE_EXTENSIONS.length - 1;
+        if (mapImageType < MAP_TYPE_URL_DEFINED || mapImageType > supportedTypesMax) {
             return false;
         }
         this.mMapImageType = mapImageType;
         byte[] urlBytes = Arrays.copyOfRange(buffer, 1, buffer.length);
-        try {
-            mMapImageUrl = new URL(new String(urlBytes));
-        } catch (MalformedURLException e) {
-            mMapImageUrl = null;
-            return false;
-        }
+        mMapImageUri = Uri.parse(new String(urlBytes, StandardCharsets.UTF_8));
         return true;
     }
 
     /**
+     * Convert an image type code to a Mime type
+     *
+     * @param imageTypeCode encoded as an integer
+     * @return the mime type of the image file
+     */
+    private String imageTypeToMime(int imageTypeCode, String imageUrl) {
+        int supportedExtensionsMax = SUPPORTED_IMAGE_FILE_EXTENSIONS.length - 1;
+        if ((imageTypeCode == 0 && imageUrl == null) || imageTypeCode > supportedExtensionsMax) {
+            return null;
+        }
+        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+        if (imageTypeCode == 0) {
+            return mimeTypeMap.getMimeTypeFromExtension(
+                    MimeTypeMap.getFileExtensionFromUrl(imageUrl));
+        } else {
+            return mimeTypeMap.getMimeTypeFromExtension(
+                    SUPPORTED_IMAGE_FILE_EXTENSIONS[imageTypeCode]);
+        }
+    }
+
+    /**
      * Converts a byte array containing fields of variable size, into an array of longs where the
      * field boundaries are defined in a constant int array passed as an argument.
      *
@@ -927,18 +897,21 @@
         mAltitudeUncertainty = UNCERTAINTY_UNDEFINED;
         mAltitude = 0;
         mDatum = DATUM_UNDEFINED;
-        mLciFlags = 0;
+        mLciRegisteredLocationAgreement = false;
+        mLciRegisteredLocationDse = false;
+        mLciDependentStation = false;
+        mLciVersion = 0;
     }
 
     /**
      * Sets the Z subelement fields to the default values when undefined.
      */
-    private void setZSubelementDefaults() {
+    private void setZaxisSubelementDefaults() {
         mIsZValid = false;
         mExpectedToMove = 0;
-        mStaFloorNumber = 0;
-        mStaHeightAboveFloorMeters = 0;
-        mStaHeightAboveFloorUncertaintyMeters = 0;
+        mFloorNumber = 0;
+        mHeightAboveFloorMeters = 0;
+        mHeightAboveFloorUncertaintyMeters = 0;
     }
 
     /**
@@ -976,7 +949,7 @@
     private void setMapImageSubelementDefaults() {
         mIsMapImageValid = false;
         mMapImageType = MAP_TYPE_URL_DEFINED;
-        mMapImageUrl = null;
+        mMapImageUri = null;
     }
 
     @Override
@@ -1003,12 +976,15 @@
                 && mAltitudeUncertainty == other.mAltitudeUncertainty
                 && mAltitude == other.mAltitude
                 && mDatum == other.mDatum
-                && mLciFlags == other.mLciFlags
+                && mLciRegisteredLocationAgreement == other.mLciRegisteredLocationAgreement
+                && mLciRegisteredLocationDse == other.mLciRegisteredLocationDse
+                && mLciDependentStation == other.mLciDependentStation
+                && mLciVersion == other.mLciVersion
                 && mExpectedToMove == other.mExpectedToMove
-                && mStaFloorNumber == other.mStaFloorNumber
-                && mStaHeightAboveFloorMeters == other.mStaHeightAboveFloorMeters
-                && mStaHeightAboveFloorUncertaintyMeters
-                        == other.mStaHeightAboveFloorUncertaintyMeters
+                && mFloorNumber == other.mFloorNumber
+                && mHeightAboveFloorMeters == other.mHeightAboveFloorMeters
+                && mHeightAboveFloorUncertaintyMeters
+                        == other.mHeightAboveFloorUncertaintyMeters
                 && mUsageRetransmit == other.mUsageRetransmit
                 && mUsageRetentionExpires == other.mUsageRetentionExpires
                 && mUsageExtraInfoOnAssociation == other.mUsageExtraInfoOnAssociation
@@ -1017,7 +993,7 @@
                 && mCivicLocationString.equals(other.mCivicLocationString)
                 && Objects.equals(mCivicLocation, other.mCivicLocation)
                 && mMapImageType == other.mMapImageType
-                && Objects.equals(mMapImageUrl, other.mMapImageUrl);
+                && Objects.equals(mMapImageUri, other.mMapImageUri);
     }
 
     @Override
@@ -1025,10 +1001,12 @@
         return Objects.hash(mIsValid, mIsLciValid, mIsZValid, mIsUsageValid, mIsBssidListValid,
                 mIsLocationCivicValid, mIsMapImageValid, mLatitudeUncertainty, mLatitude,
                 mLongitudeUncertainty, mLongitude, mAltitudeType, mAltitudeUncertainty, mAltitude,
-                mDatum, mLciFlags, mExpectedToMove, mStaFloorNumber, mStaHeightAboveFloorMeters,
-                mStaHeightAboveFloorUncertaintyMeters, mUsageRetransmit, mUsageRetentionExpires,
+                mDatum, mLciRegisteredLocationAgreement,
+                mLciRegisteredLocationDse, mLciDependentStation, mLciVersion,
+                mExpectedToMove, mFloorNumber, mHeightAboveFloorMeters,
+                mHeightAboveFloorUncertaintyMeters, mUsageRetransmit, mUsageRetentionExpires,
                 mUsageExtraInfoOnAssociation, mBssidList, mCivicLocationCountryCode,
-                mCivicLocationString, mCivicLocation, mMapImageType, mMapImageUrl);
+                mCivicLocationString, mCivicLocation, mMapImageType, mMapImageUri);
     }
 
     /**
@@ -1059,198 +1037,267 @@
 
     /**
      * @return the latitude uncertainty in degrees.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
-     *
+     * </p>
      * <p> An unknown uncertainty is indicated by 0.</p>
      */
     public double getLatitudeUncertainty() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false)");
+                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mLatitudeUncertainty;
     }
 
     /**
      * @return the latitude in degrees
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
      */
     public double getLatitude() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLatitude(): invoked on an invalid result: mIsLciValid = false)");
+                "getLatitude(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mLatitude;
     }
 
     /**
      * @return the Longitude uncertainty in degrees.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
-     *
+     * </p>
      * <p> An unknown uncertainty is indicated by 0.</p>
      */
     public double getLongitudeUncertainty() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLongitudeUncertainty(): invoked on an invalid result: mIsLciValid = false)");
+                "getLongitudeUncertainty(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mLongitudeUncertainty;
     }
 
     /**
      * @return the Longitude in degrees..
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
      */
     public double getLongitude() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false)");
+                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mLongitude;
     }
 
     /**
      * @return the Altitude type.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
      */
     @AltitudeType
     public int getAltitudeType() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false)");
+                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mAltitudeType;
     }
 
     /**
      * @return the Altitude uncertainty in meters.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
-     *
+     * </p>
      * <p>An unknown uncertainty is indicated by 0.</p>
      */
     public double getAltitudeUncertainty() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false)");
+                "getLatitudeUncertainty(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mAltitudeUncertainty;
     }
 
     /**
      * @return the Altitude in units defined by the altitude type.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
      */
     public double getAltitude() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getAltitude(): invoked on an invalid result: mIsLciValid = false)");
+                "getAltitude(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mAltitude;
     }
 
     /**
      * @return the Datum used for the LCI positioning information.
-     *
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
      */
     @DatumType
     public int getDatum() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getDatum(): invoked on an invalid result: mIsLciValid = false)");
+                "getDatum(): invoked on an invalid result: mIsLciValid = false.");
         }
         return mDatum;
     }
 
     /**
-     * @return the LCI sub-element flags (5-bits).
-     *
+     * @return true if the station is operating within a national policy area or an international
+     * agreement area near a national border, otherwise false
+     * (see 802.11REVmc Section 11.12.3 - Registered STA Operation).
+     * <p>
      * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
-     *
-     * <p>Note: The flags/version can be extracted by bitwise ANDing this value with the
-     * corresponding LCI_FLAGS_MASK_* .</p>
      */
-    public int getLciFlags() {
+    public boolean getRegisteredLocationAgreementIndication() {
         if (!mIsLciValid) {
             throw new IllegalStateException(
-                "getLciFlags(): invoked on an invalid result: mIsLciValid = false)");
+                "getRegisteredLocationAgreementIndication(): "
+                        + "invoked on an invalid result: mIsLciValid = false.");
         }
-        return mLciFlags;
+        return mLciRegisteredLocationAgreement;
+    }
+
+    /**
+     * @return true indicating this is an enabling station, enabling the operation of nearby STAs
+     * with Dynamic Station Enablement (DSE), otherwise false.
+     * (see 802.11REVmc Section 11.12.3 - Registered STA Operation).
+     * <p>
+     * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
+     */
+    public boolean getRegisteredLocationDseIndication() {
+        if (!mIsLciValid) {
+            throw new IllegalStateException(
+                "getRegisteredLocationDseIndication(): "
+                    + "invoked on an invalid result: mIsLciValid = false.");
+        }
+        return mLciRegisteredLocationDse;
+    }
+
+    /**
+     * @return true indicating this is a dependent station that is operating with the enablement of
+     * an enabling station whose LCI is being reported, otherwise false.
+     * (see 802.11REVmc Section 11.12.3 - Registered STA Operation).
+     * <p>
+     * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
+     */
+    public boolean getDependentStationIndication() {
+        if (!mIsLciValid) {
+            throw new IllegalStateException(
+                "getDependentStationIndication(): "
+                    + "invoked on an invalid result: mIsLciValid = false.");
+        }
+        return mLciDependentStation;
+    }
+
+    /**
+     * @return a value greater or equal to 1, indicating the current version number
+     * of the LCI protocol.
+     * <p>
+     * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
+     */
+    public int getLciVersion() {
+        if (!mIsLciValid) {
+            throw new IllegalStateException(
+                "getLciVersion(): "
+                    + "invoked on an invalid result: mIsLciValid = false.");
+        }
+        return mLciVersion;
+    }
+
+    /**
+     * @return the LCI location represented as a {@link Location} object (best effort).
+     * <p>
+     * Only valid if {@link #isLciSubelementValid()} returns true, or will throw an exception.
+     */
+    @NonNull
+    public Location toLocation() {
+        if (!mIsLciValid) {
+            throw new IllegalStateException(
+                "toLocation(): "
+                    + "invoked on an invalid result: mIsLciValid = false.");
+        }
+        Location location = new Location(LOCATION_PROVIDER);
+        location.setLatitude(mLatitude);
+        location.setLongitude(mLongitude);
+        location.setAccuracy((float) (mLatitudeUncertainty + mLongitudeUncertainty) / 2);
+        location.setAltitude(mAltitude);
+        location.setVerticalAccuracyMeters((float) mAltitudeUncertainty);
+        location.setTime(System.currentTimeMillis());
+        return location;
     }
 
     /**
      * @return if the Z subelement (containing mobility, Floor, Height above floor) is valid.
      */
-    public boolean isZsubelementValid() {
+    public boolean isZaxisSubelementValid() {
         return mIsZValid;
     }
 
     /**
      * @return an integer representing the mobility of the responder.
-     *
-     * Only valid if {@link #isZsubelementValid()} returns true, or will throw an exception.
+     * <p>
+     * Only valid if {@link #isZaxisSubelementValid()} returns true, or will throw an exception.
      */
     @ExpectedToMoveType
     public int getExpectedToMove() {
         if (!mIsZValid) {
             throw new IllegalStateException(
-                "getExpectedToMove(): invoked on an invalid result: mIsZValid = false)");
+                "getExpectedToMove(): invoked on an invalid result: mIsZValid = false.");
         }
         return mExpectedToMove;
     }
 
     /**
-     * @return the Z sub element STA Floor Number.
-     *
-     * Only valid if {@link #isZsubelementValid()} returns true, or will throw an exception.
-     *
+     * @return the Z sub element Floor Number.
+     * <p>
+     * Only valid if {@link #isZaxisSubelementValid()} returns true, or will throw an exception.
+     * </p>
      * <p>Note: this number can be positive or negative, with value increments of +/- 1/16 of a
      * floor.</p>.
      */
-    public double getStaFloorNumber() {
+    public double getFloorNumber() {
         if (!mIsZValid) {
             throw new IllegalStateException(
-                "getStaFloorNumber(): invoked on an invalid result: mIsZValid = false)");
+                "getFloorNumber(): invoked on an invalid result: mIsZValid = false)");
         }
-        return mStaFloorNumber;
+        return mFloorNumber;
     }
 
     /**
-     * @return the Z subelement STA Height above the floor in meters.
-     *
-     * Only valid if {@link #isZsubelementValid()} returns true, or will throw an exception.
-     *
+     * @return the Z subelement Height above the floor in meters.
+     * <p>
+     * Only valid if {@link #isZaxisSubelementValid()} returns true, or will throw an exception.
+     * </p>
      * <p>This value can be positive or negative. </p>
      */
-    public double getStaHeightAboveFloorMeters() {
+    public double getHeightAboveFloorMeters() {
         if (!mIsZValid) {
             throw new IllegalStateException(
-                "getStaHeightAboveFloorMeters(): invoked on an invalid result: mIsZValid = false)");
+                "getHeightAboveFloorMeters(): invoked on an invalid result: mIsZValid = false)");
         }
-        return mStaHeightAboveFloorMeters;
+        return mHeightAboveFloorMeters;
     }
 
     /**
-     * @return the Z subelement STA Height above the floor uncertainty in meters.
-     *
-     * Only valid if {@link #isZsubelementValid()} returns true, or will throw an exception.
-     *
+     * @return the Z subelement Height above the floor uncertainty in meters.
+     * <p>
+     * Only valid if {@link #isZaxisSubelementValid()} returns true, or will throw an exception.
+     * </p>
      * <p>An unknown uncertainty is indicated by 0.</p>
      */
-    public double getStaHeightAboveFloorUncertaintyMeters() {
+    public double getHeightAboveFloorUncertaintyMeters() {
         if (!mIsZValid) {
             throw new IllegalStateException(
-                "getStaHeightAboveFloorUncertaintyMeters():"
+                "getHeightAboveFloorUncertaintyMeters():"
                     + "invoked on an invalid result: mIsZValid = false)");
         }
-        return mStaHeightAboveFloorUncertaintyMeters;
+        return mHeightAboveFloorUncertaintyMeters;
     }
 
     /**
@@ -1267,7 +1314,6 @@
      * @return true if location-data received should expire (and be deleted)
      * by the time provided in the getRelativeExpirationTimeHours() method.
      *
-     *
      * @hide
      */
     public boolean getRetentionExpiresIndication() {
@@ -1285,20 +1331,18 @@
     }
 
     /**
-     * @return the list of colocated BSSIDs at the responder.
+     * @return the Immutable list of colocated BSSIDs at the responder.
      *
      * <p> Will return an empty list when there are no bssids listed.
      */
     public List<MacAddress> getColocatedBssids() {
-        return mBssidList;
+        return Collections.unmodifiableList(mBssidList);
     }
 
     /**
      * @return the civic location represented as an {@link Address} object (best effort).
      *
-     * <p> Will return a {@code null} when there is no Civic Location define defined.
-     *
-     * @hide
+     * <p> Will return a {@code null} when there is no Civic Location defined.
      */
     @Nullable
     public Address toCivicLocationAddress() {
@@ -1309,6 +1353,22 @@
         }
     }
 
+    /**
+     * @return the civic location represented as a {@link SparseArray}
+     * <p>
+     * Valid keys to access the SparseArray can be found in {@code CivicLocationKeys}.
+     * </p>
+     * <p> Will return a {@code null} when there is no Civic Location defined.
+     *
+     */
+    @Nullable
+    public SparseArray toCivicLocationSparseArray() {
+        if (mCivicLocation != null && mCivicLocation.isValid()) {
+            return mCivicLocation.toSparseArray();
+        } else {
+            return null;
+        }
+    }
 
     /**
      * @return the civic location two upper-case ASCII character country code defined in ISO 3166.
@@ -1337,20 +1397,24 @@
     }
 
     /**
-     * @return the Map Image file type, referred to by getMapImageUrl(), encoded as an integer.
+     * @return the Map Image file Mime type, referred to by getMapImageUrl().
      */
-    @MapImageType
-    public int getMapImageType() {
-        return mMapImageType;
+    @Nullable
+    public String getMapImageMimeType() {
+        if (mMapImageUri == null) {
+            return null;
+        } else {
+            return imageTypeToMime(mMapImageType, mMapImageUri.toString());
+        }
     }
 
     /**
-     * @return a Url referencing a map-file showing the local floor plan.
+     * @return a URI referencing a map-file showing the local floor plan.
      *
-     * <p> Will return a {@code null} when there is no URL defined.
+     * <p> Will return a {@code null} when there is no URI defined.
      */
     @Nullable
-    public URL getMapImageUrl() {
-        return mMapImageUrl;
+    public Uri getMapImageUri() {
+        return mMapImageUri;
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 449423f..d927052 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -293,4 +293,59 @@
         assertEquals(config.apChannel, restoredConfig.apChannel);
         assertEquals(config.hiddenSSID, restoredConfig.hiddenSSID);
     }
+
+
+    /**
+     * Verifies that getKeyIdForCredentials returns the expected string for Enterprise networks
+     * @throws Exception
+     */
+    @Test
+    public void testGetKeyIdForCredentials() throws Exception {
+        WifiConfiguration config = new WifiConfiguration();
+        final String mSsid = "TestAP";
+        config.SSID = mSsid;
+
+        // Test various combinations
+        // EAP with TLS
+        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+        String keyId = config.getKeyIdForCredentials(config);
+        assertEquals(keyId, mSsid + "_WPA_EAP_TLS_NULL");
+
+        // EAP with TTLS & MSCHAPv2
+        config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
+        keyId = config.getKeyIdForCredentials(config);
+        assertEquals(keyId, mSsid + "_WPA_EAP_TTLS_MSCHAPV2");
+
+        // Suite-B 192 with PWD & GTC
+        config.allowedKeyManagement.clear();
+        config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PWD);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+        keyId = config.getKeyIdForCredentials(config);
+        assertEquals(keyId, mSsid + "_SUITE_B_192_PWD_GTC");
+
+        // IEEE8021X with SIM
+        config.allowedKeyManagement.clear();
+        config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+        config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+        keyId = config.getKeyIdForCredentials(config);
+        assertEquals(keyId, mSsid + "_IEEE8021X_SIM_NULL");
+
+        // Try calling this method with non-Enterprise network, expect an exception
+        boolean exceptionThrown = false;
+        try {
+            config.allowedKeyManagement.clear();
+            config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+            config.preSharedKey = "TestPsk";
+            keyId = config.getKeyIdForCredentials(config);
+        } catch (IllegalStateException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
index 560c88e..01a4c53 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
@@ -73,4 +73,44 @@
             fail("expected IllegalArgumentException");
         } catch (IllegalArgumentException e) { }
     }
+
+    /**
+     * Check passphrase setter
+     */
+    @Test
+    public void testBuilderInvalidPassphrase() throws Exception {
+        WifiP2pConfig.Builder b = new WifiP2pConfig.Builder();
+
+        // sunny case
+        try {
+            b.setPassphrase("abcd1234");
+        } catch (IllegalArgumentException e) {
+            fail("Unexpected IllegalArgumentException");
+        }
+
+        // null string.
+        try {
+            b.setPassphrase(null);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected exception.
+        }
+
+        // less than 8 characters.
+        try {
+            b.setPassphrase("12abcde");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected exception.
+        }
+
+        // more than 63 characters.
+        try {
+            b.setPassphrase(
+                    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+/");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected exception.
+        }
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java b/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
index 9efb642..47c30409 100644
--- a/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/ResponderLocationTest.java
@@ -17,8 +17,10 @@
 package android.net.wifi.rtt;
 
 import android.location.Address;
+import android.location.Location;
 import android.net.MacAddress;
 import android.os.Parcel;
+import android.webkit.MimeTypeMap;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -35,7 +37,7 @@
  */
 @RunWith(JUnit4.class)
 public class ResponderLocationTest {
-    private static final double LATLNG_TOLERANCE_DEGREES = 0.001;
+    private static final double LATLNG_TOLERANCE_DEGREES = 0.00001;
     private static final double ALT_TOLERANCE_METERS = 0.01;
     private static final double HEIGHT_TOLERANCE_METERS = 0.01;
     private static final int INDEX_ELEMENT_TYPE = 2;
@@ -170,7 +172,7 @@
     private static final byte[] sTestMapUrlSE = {
             (byte) 5, // Map URL Subelement
             (byte) 25,
-            (byte) ResponderLocation.MAP_TYPE_URL_DEFINED,
+            (byte) 0, // MAP_TYPE_URL_DEFINED
             (byte) 'h',
             (byte) 't',
             (byte) 't',
@@ -206,7 +208,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -222,7 +224,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -240,7 +242,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -258,7 +260,8 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
+        Location location = responderLocation.toLocation();
 
         assertTrue(valid);
         assertTrue(lciValid);
@@ -273,11 +276,20 @@
         assertEquals(64.0, responderLocation.getAltitudeUncertainty());
         assertEquals(11.2, responderLocation.getAltitude(), ALT_TOLERANCE_METERS);
         assertEquals(1, responderLocation.getDatum()); // WGS84
-        int lciFlags = responderLocation.getLciFlags();
-        assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_REGLOC_AGREEMENT);
-        assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_REGLOC_DSE);
-        assertEquals(0, lciFlags & ResponderLocation.LCI_FLAGS_MASK_DEPENDENT_STA);
-        assertEquals(1, lciFlags & ResponderLocation.LCI_FLAGS_MASK_VERSION);
+        assertEquals(false, responderLocation.getRegisteredLocationAgreementIndication());
+        assertEquals(false, responderLocation.getRegisteredLocationDseIndication());
+        assertEquals(false, responderLocation.getDependentStationIndication());
+        assertEquals(1, responderLocation.getLciVersion());
+
+        // Testing Location Object
+        assertEquals(-33.857009, location.getLatitude(),
+                LATLNG_TOLERANCE_DEGREES);
+        assertEquals(151.215200, location.getLongitude(),
+                LATLNG_TOLERANCE_DEGREES);
+        assertEquals((0.0009765625 + 0.0009765625) / 2, location.getAccuracy(),
+                LATLNG_TOLERANCE_DEGREES);
+        assertEquals(11.2, location.getAltitude(), ALT_TOLERANCE_METERS);
+        assertEquals(64.0, location.getVerticalAccuracyMeters(), ALT_TOLERANCE_METERS);
     }
 
     /**
@@ -292,7 +304,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -312,7 +324,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -332,7 +344,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -352,7 +364,7 @@
 
         boolean valid = responderLocation.isValid();
         boolean lciValid = responderLocation.isLciSubelementValid();
-        boolean zValid = responderLocation.isZsubelementValid();
+        boolean zValid = responderLocation.isZaxisSubelementValid();
 
         assertFalse(valid);
         assertFalse(lciValid);
@@ -370,12 +382,12 @@
                 new ResponderLocation(testBuffer, sTestLcrBufferHeader);
 
         boolean isValid = responderLocation.isValid();
-        boolean isZValid = responderLocation.isZsubelementValid();
+        boolean isZValid = responderLocation.isZaxisSubelementValid();
         boolean isLciValid = responderLocation.isLciSubelementValid();
-        double staFloorNumber = responderLocation.getStaFloorNumber();
-        double staHeightAboveFloorMeters = responderLocation.getStaHeightAboveFloorMeters();
+        double staFloorNumber = responderLocation.getFloorNumber();
+        double staHeightAboveFloorMeters = responderLocation.getHeightAboveFloorMeters();
         double staHeightAboveFloorUncertaintyMeters =
-                responderLocation.getStaHeightAboveFloorUncertaintyMeters();
+                responderLocation.getHeightAboveFloorUncertaintyMeters();
 
         assertTrue(isValid);
         assertTrue(isZValid);
@@ -496,20 +508,21 @@
      * Test that a URL can be extracted from a valid lcr buffer with a map image subelement.
      */
     @Test
-    public void testLcrCheckMapUrlIsValid() {
+    public void testLcrCheckMapUriIsValid() {
         byte[] testLciBuffer = concatenateArrays(sTestLciIeHeader, sTestLciSE);
         byte[] testLcrBuffer = concatenateArrays(sTestLcrBufferHeader, sTestMapUrlSE);
         ResponderLocation responderLocation = new ResponderLocation(testLciBuffer, testLcrBuffer);
 
         boolean valid = responderLocation.isValid();
-        int mapImageType = responderLocation.getMapImageType();
+        String mapImageMimeType = responderLocation.getMapImageMimeType();
         String urlString = "";
-        if (responderLocation.getMapImageUrl() != null) {
-            urlString = responderLocation.getMapImageUrl().toString();
+        if (responderLocation.getMapImageUri() != null) {
+            urlString = responderLocation.getMapImageUri().toString();
         }
 
         assertTrue(valid);
-        assertEquals(ResponderLocation.MAP_TYPE_URL_DEFINED, mapImageType);
+        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
+        assertEquals(mimeTypeMap.getMimeTypeFromExtension("jpg"), mapImageMimeType);
         assertEquals("https://map.com/mall.jpg", urlString);
     }