Merge "AudioService: fix audio mode lock" into qt-dev
diff --git a/Android.bp b/Android.bp
index c3025e8..b4110fa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -920,6 +920,7 @@
         "core/java/com/android/internal/util/RingBufferIndices.java",
         "core/java/com/android/internal/util/State.java",
         "core/java/com/android/internal/util/StateMachine.java",
+        "core/java/com/android/internal/util/TrafficStatsConstants.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
         "core/java/android/net/shared/*.java",
     ]
diff --git a/api/current.txt b/api/current.txt
index 34ba3fc..f602c9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -224,6 +224,7 @@
     field public static final int __removed3 = 16844187; // 0x101059b
     field public static final int __removed4 = 16844188; // 0x101059c
     field public static final int __removed5 = 16844189; // 0x101059d
+    field public static final int __removed6 = 16844182; // 0x1010596
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -750,7 +751,6 @@
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
     field public static final int importantForAutofill = 16844120; // 0x1010558
-    field public static final int importantForContentCapture = 16844182; // 0x1010596
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -6235,14 +6235,14 @@
   }
 
   public class TaskInfo {
-    field public android.content.ComponentName baseActivity;
-    field public android.content.Intent baseIntent;
+    field @Nullable public android.content.ComponentName baseActivity;
+    field @NonNull public android.content.Intent baseIntent;
     field public boolean isRunning;
     field public int numActivities;
-    field public android.content.ComponentName origActivity;
-    field public android.app.ActivityManager.TaskDescription taskDescription;
+    field @Nullable public android.content.ComponentName origActivity;
+    field @Nullable public android.app.ActivityManager.TaskDescription taskDescription;
     field public int taskId;
-    field public android.content.ComponentName topActivity;
+    field @Nullable public android.content.ComponentName topActivity;
   }
 
   public class TaskStackBuilder {
@@ -25138,25 +25138,6 @@
     field public static final int TYPE_STRING = 4; // 0x4
   }
 
-  public final class MediaItem2 implements android.os.Parcelable {
-    method public int describeContents();
-    method public long getEndPosition();
-    method @Nullable public android.media.MediaMetadata getMetadata();
-    method public long getStartPosition();
-    method public void setMetadata(@Nullable android.media.MediaMetadata);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.MediaItem2> CREATOR;
-    field public static final long POSITION_UNKNOWN = 576460752303423487L; // 0x7ffffffffffffffL
-  }
-
-  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);
-    method @NonNull public android.media.MediaItem2.Builder setMetadata(@Nullable android.media.MediaMetadata);
-    method @NonNull public android.media.MediaItem2.Builder setStartPosition(long);
-  }
-
   public final class MediaMetadata implements android.os.Parcelable {
     method public boolean containsKey(String);
     method public int describeContents();
@@ -26177,8 +26158,8 @@
     ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
     method public int describeContents();
     method public int getCommandCode();
-    method @Nullable public String getCustomCommand();
-    method @Nullable public android.os.Bundle getExtras();
+    method @Nullable public String getCustomAction();
+    method @Nullable public android.os.Bundle getCustomExtras();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
     field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
@@ -38625,6 +38606,7 @@
     field public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
     field public static final String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
     field public static final String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
+    field public static final String ACTION_APP_BATTERY_SETTINGS = "android.settings.APP_BATTERY_SETTINGS";
     field public static final String ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS = "android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS";
     field public static final String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS";
     field public static final String ACTION_APP_SEARCH_SETTINGS = "android.settings.APP_SEARCH_SETTINGS";
@@ -41776,7 +41758,7 @@
     method public int getDisabledShowContext();
     method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
     method public android.os.IBinder onBind(android.content.Intent);
-    method @Nullable public java.util.Set<java.lang.String> onGetSupportedVoiceActions(@NonNull java.util.Set<java.lang.String>);
+    method @NonNull public java.util.Set<java.lang.String> onGetSupportedVoiceActions(@NonNull java.util.Set<java.lang.String>);
     method public void onLaunchVoiceAssistFromKeyguard();
     method public void onReady();
     method public void onShutdown();
@@ -47818,6 +47800,10 @@
     method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
+    field public static final int DENSITY_140 = 140; // 0x8c
+    field public static final int DENSITY_180 = 180; // 0xb4
+    field public static final int DENSITY_200 = 200; // 0xc8
+    field public static final int DENSITY_220 = 220; // 0xdc
     field public static final int DENSITY_260 = 260; // 0x104
     field public static final int DENSITY_280 = 280; // 0x118
     field public static final int DENSITY_300 = 300; // 0x12c
@@ -50201,7 +50187,6 @@
     method @android.view.ViewDebug.CapturedViewProperty @IdRes public int getId();
     method @android.view.ViewDebug.ExportedProperty(category="accessibility", mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, to="noHideDescendants")}) public int getImportantForAccessibility();
     method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForAutofill();
-    method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to="auto"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES, to="yes"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO, to="no"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS, to="yesExcludeDescendants"), @android.view.ViewDebug.IntToString(from=android.view.View.IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS, to="noExcludeDescendants")}) public int getImportantForContentCapture();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method @android.view.ViewDebug.ExportedProperty(category="accessibility") @IdRes public int getLabelFor();
@@ -50342,7 +50327,6 @@
     method @android.view.ViewDebug.ExportedProperty public boolean isHovered();
     method public boolean isImportantForAccessibility();
     method public final boolean isImportantForAutofill();
-    method public final boolean isImportantForContentCapture();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method @android.view.ViewDebug.ExportedProperty public boolean isInTouchMode();
@@ -50417,7 +50401,6 @@
     method @CallSuper public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutofillStructure(android.view.ViewStructure, int);
     method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
-    method public void onProvideContentCaptureStructure(@NonNull android.view.ViewStructure, int);
     method public void onProvideStructure(android.view.ViewStructure);
     method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -50543,7 +50526,6 @@
     method public void setId(@IdRes int);
     method public void setImportantForAccessibility(int);
     method public void setImportantForAutofill(int);
-    method public void setImportantForContentCapture(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(@IdRes int);
@@ -50722,11 +50704,6 @@
     field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
-    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
-    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
-    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
-    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
-    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -51532,6 +51509,7 @@
     method public android.transition.Transition getSharedElementReturnTransition();
     method public boolean getSharedElementsUseOverlay();
     method @ColorInt public abstract int getStatusBarColor();
+    method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects();
     method public long getTransitionBackgroundFadeDuration();
     method public android.transition.TransitionManager getTransitionManager();
     method public abstract int getVolumeControlStream();
@@ -51610,6 +51588,7 @@
     method public void setSoftInputMode(int);
     method public abstract void setStatusBarColor(@ColorInt int);
     method public void setSustainedPerformanceMode(boolean);
+    method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>);
     method public abstract void setTitle(CharSequence);
     method @Deprecated public abstract void setTitleColor(@ColorInt int);
     method public void setTransitionBackgroundFadeDuration(long);
@@ -52834,7 +52813,7 @@
     method @Nullable public java.util.Set<android.view.contentcapture.ContentCaptureCondition> getContentCaptureConditions();
     method @Nullable public android.content.ComponentName getServiceComponentName();
     method public boolean isContentCaptureEnabled();
-    method public void removeUserData(@NonNull android.view.contentcapture.UserDataRemovalRequest);
+    method public void removeData(@NonNull android.view.contentcapture.DataRemovalRequest);
     method public void setContentCaptureEnabled(boolean);
   }
 
@@ -52845,6 +52824,7 @@
     method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
     method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId();
     method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long);
+    method @NonNull public final android.view.ViewStructure newViewStructure(@NonNull android.view.View);
     method @NonNull public final android.view.ViewStructure newVirtualViewStructure(@NonNull android.view.autofill.AutofillId, long);
     method public final void notifyViewAppeared(@NonNull android.view.ViewStructure);
     method public final void notifyViewDisappeared(@NonNull android.view.autofill.AutofillId);
@@ -52859,24 +52839,24 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureSessionId> CREATOR;
   }
 
-  public final class UserDataRemovalRequest implements android.os.Parcelable {
+  public final class DataRemovalRequest implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.LocusIdRequest> getLocusIdRequests();
+    method @NonNull public java.util.List<android.view.contentcapture.DataRemovalRequest.LocusIdRequest> getLocusIdRequests();
     method @NonNull public String getPackageName();
     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 @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.DataRemovalRequest> 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, int);
-    method @NonNull public android.view.contentcapture.UserDataRemovalRequest build();
-    method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
+  public static final class DataRemovalRequest.Builder {
+    ctor public DataRemovalRequest.Builder();
+    method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, int);
+    method @NonNull public android.view.contentcapture.DataRemovalRequest build();
+    method @NonNull public android.view.contentcapture.DataRemovalRequest.Builder forEverything();
   }
 
-  public final class UserDataRemovalRequest.LocusIdRequest {
+  public final class DataRemovalRequest.LocusIdRequest {
     method @NonNull public int getFlags();
     method @NonNull public android.content.LocusId getLocusId();
   }
@@ -53426,6 +53406,7 @@
     method public int describeContents();
     method @Nullable public String getCallingPackageName();
     method @NonNull public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
+    method @NonNull public android.os.Bundle getExtras();
     method @Nullable public java.util.List<java.lang.String> getHints();
     method @IntRange(from=0xffffffff) public int getMaxSuggestions();
     method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
@@ -53438,6 +53419,7 @@
   public static final class ConversationActions.Request.Builder {
     ctor public ConversationActions.Request.Builder(@NonNull java.util.List<android.view.textclassifier.ConversationActions.Message>);
     method @NonNull public android.view.textclassifier.ConversationActions.Request build();
+    method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setExtras(@Nullable android.os.Bundle);
     method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setHints(@Nullable java.util.List<java.lang.String>);
     method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(@IntRange(from=0xffffffff) int);
     method @NonNull public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
@@ -53634,29 +53616,23 @@
     method @NonNull public android.view.textclassifier.TextClassifier.EntityConfig.Builder setIncludedTypes(@Nullable java.util.Collection<java.lang.String>);
   }
 
-  public final class TextClassifierEvent implements android.os.Parcelable {
+  public abstract class TextClassifierEvent implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public int[] getActionIndices();
     method @NonNull public String[] getEntityTypes();
     method public int getEventCategory();
     method @Nullable public android.view.textclassifier.TextClassificationContext getEventContext();
     method public int getEventIndex();
-    method public long getEventTime();
     method public int getEventType();
     method @NonNull public android.os.Bundle getExtras();
-    method @Nullable public String getLanguage();
-    method public int getRelativeSuggestedWordEndIndex();
-    method public int getRelativeSuggestedWordStartIndex();
-    method public int getRelativeWordEndIndex();
-    method public int getRelativeWordStartIndex();
+    method @Nullable public String getModelName();
     method @Nullable public String getResultId();
-    method public float getScore();
+    method @NonNull public float[] getScores();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CATEGORY_CONVERSATION_ACTIONS = 3; // 0x3
     field public static final int CATEGORY_LANGUAGE_DETECTION = 4; // 0x4
     field public static final int CATEGORY_LINKIFY = 2; // 0x2
     field public static final int CATEGORY_SELECTION = 1; // 0x1
-    field public static final int CATEGORY_UNDEFINED = 0; // 0x0
     field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent> CREATOR;
     field public static final int TYPE_ACTIONS_GENERATED = 20; // 0x14
     field public static final int TYPE_ACTIONS_SHOWN = 6; // 0x6
@@ -53678,25 +53654,63 @@
     field public static final int TYPE_SMART_ACTION = 13; // 0xd
     field public static final int TYPE_SMART_SELECTION_MULTI = 4; // 0x4
     field public static final int TYPE_SMART_SELECTION_SINGLE = 3; // 0x3
-    field public static final int TYPE_UNDEFINED = 0; // 0x0
   }
 
-  public static final class TextClassifierEvent.Builder {
-    ctor public TextClassifierEvent.Builder(int, int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent build();
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setActionIndices(@NonNull int...);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEntityTypes(@NonNull java.lang.String...);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventIndex(int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setEventTime(long);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setExtras(@NonNull android.os.Bundle);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setLanguage(@Nullable String);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordEndIndex(int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeSuggestedWordStartIndex(int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordEndIndex(int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setRelativeWordStartIndex(int);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setResultId(@Nullable String);
-    method @NonNull public android.view.textclassifier.TextClassifierEvent.Builder setScore(float);
+  public abstract static class TextClassifierEvent.Builder<T extends android.view.textclassifier.TextClassifierEvent.Builder<T>> {
+    method @NonNull public T setActionIndices(@NonNull int...);
+    method @NonNull public T setEntityTypes(@NonNull java.lang.String...);
+    method @NonNull public T setEventContext(@Nullable android.view.textclassifier.TextClassificationContext);
+    method @NonNull public T setEventIndex(int);
+    method @NonNull public T setExtras(@NonNull android.os.Bundle);
+    method @NonNull public T setModelName(@Nullable String);
+    method @NonNull public T setResultId(@Nullable String);
+    method @NonNull public T setScores(@NonNull float...);
+  }
+
+  public static final class TextClassifierEvent.ConversationActionsEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent> CREATOR;
+  }
+
+  public static final class TextClassifierEvent.ConversationActionsEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent.Builder> {
+    ctor public TextClassifierEvent.ConversationActionsEvent.Builder(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.ConversationActionsEvent build();
+  }
+
+  public static final class TextClassifierEvent.LanguageDetectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+    method @Nullable public android.icu.util.ULocale getLocale();
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent> CREATOR;
+  }
+
+  public static final class TextClassifierEvent.LanguageDetectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder> {
+    ctor public TextClassifierEvent.LanguageDetectionEvent.Builder(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent build();
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.LanguageDetectionEvent.Builder setLocale(@Nullable android.icu.util.ULocale);
+  }
+
+  public static final class TextClassifierEvent.TextLinkifyEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent> CREATOR;
+  }
+
+  public static final class TextClassifierEvent.TextLinkifyEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent.Builder> {
+    ctor public TextClassifierEvent.TextLinkifyEvent.Builder(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextLinkifyEvent build();
+  }
+
+  public static final class TextClassifierEvent.TextSelectionEvent extends android.view.textclassifier.TextClassifierEvent implements android.os.Parcelable {
+    method public int getRelativeSuggestedWordEndIndex();
+    method public int getRelativeSuggestedWordStartIndex();
+    method public int getRelativeWordEndIndex();
+    method public int getRelativeWordStartIndex();
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent> CREATOR;
+  }
+
+  public static final class TextClassifierEvent.TextSelectionEvent.Builder extends android.view.textclassifier.TextClassifierEvent.Builder<android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder> {
+    ctor public TextClassifierEvent.TextSelectionEvent.Builder(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent build();
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordEndIndex(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeSuggestedWordStartIndex(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordEndIndex(int);
+    method @NonNull public android.view.textclassifier.TextClassifierEvent.TextSelectionEvent.Builder setRelativeWordStartIndex(int);
   }
 
   public final class TextLanguage implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e730db..b60e850 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -604,7 +604,7 @@
   public final class Vr2dDisplayProperties implements android.os.Parcelable {
     ctor public Vr2dDisplayProperties(int, int, int);
     method public int describeContents();
-    method public void dump(java.io.PrintWriter, String);
+    method public void dump(@NonNull java.io.PrintWriter, @NonNull String);
     method public int getAddedFlags();
     method public int getDpi();
     method public int getHeight();
@@ -615,26 +615,26 @@
     field public static final int FLAG_VIRTUAL_DISPLAY_ENABLED = 1; // 0x1
   }
 
-  public static class Vr2dDisplayProperties.Builder {
+  public static final class Vr2dDisplayProperties.Builder {
     ctor public Vr2dDisplayProperties.Builder();
-    method public android.app.Vr2dDisplayProperties.Builder addFlags(int);
-    method public android.app.Vr2dDisplayProperties build();
-    method public android.app.Vr2dDisplayProperties.Builder removeFlags(int);
-    method public android.app.Vr2dDisplayProperties.Builder setDimensions(int, int, int);
-    method public android.app.Vr2dDisplayProperties.Builder setEnabled(boolean);
+    method @NonNull public android.app.Vr2dDisplayProperties.Builder addFlags(int);
+    method @NonNull public android.app.Vr2dDisplayProperties build();
+    method @NonNull public android.app.Vr2dDisplayProperties.Builder removeFlags(int);
+    method @NonNull public android.app.Vr2dDisplayProperties.Builder setDimensions(int, int, int);
+    method @NonNull public android.app.Vr2dDisplayProperties.Builder setEnabled(boolean);
   }
 
   public class VrManager {
     method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public int getVr2dDisplayId();
     method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public boolean isPersistentVrModeEnabled();
     method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public boolean isVrModeEnabled();
-    method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void registerVrStateCallback(@NonNull java.util.concurrent.Executor, android.app.VrStateCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void registerVrStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.VrStateCallback);
     method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setAndBindVrCompositor(android.content.ComponentName);
     method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setPersistentVrModeEnabled(boolean);
     method @RequiresPermission("android.permission.ACCESS_VR_MANAGER") public void setStandbyEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVr2dDisplayProperties(android.app.Vr2dDisplayProperties);
-    method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVrInputMethod(android.content.ComponentName);
-    method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void unregisterVrStateCallback(android.app.VrStateCallback);
+    method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVr2dDisplayProperties(@NonNull android.app.Vr2dDisplayProperties);
+    method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public void setVrInputMethod(@Nullable android.content.ComponentName);
+    method @RequiresPermission(anyOf={android.Manifest.permission.RESTRICTED_VR_ACCESS, "android.permission.ACCESS_VR_STATE"}) public void unregisterVrStateCallback(@NonNull android.app.VrStateCallback);
   }
 
   public abstract class VrStateCallback {
@@ -1092,12 +1092,14 @@
   }
 
   public static final class AppTarget.Builder {
-    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+    ctor @Deprecated public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
     method @NonNull public android.app.prediction.AppTarget build();
     method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
     method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
-    method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
   }
 
   public final class AppTargetEvent implements android.os.Parcelable {
@@ -4226,9 +4228,12 @@
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
     method public static void setThreadStatsTagRestore();
-    field public static final int TAG_SYSTEM_DHCP = -192; // 0xffffff40
-    field public static final int TAG_SYSTEM_DHCP_SERVER = -186; // 0xffffff46
-    field public static final int TAG_SYSTEM_PROBE = -190; // 0xffffff42
+    field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = -113; // 0xffffff8f
+    field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = -128; // 0xffffff80
+    field public static final int TAG_NETWORK_STACK_RANGE_END = -257; // 0xfffffeff
+    field public static final int TAG_NETWORK_STACK_RANGE_START = -768; // 0xfffffd00
+    field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = -241; // 0xffffff0f
+    field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00
   }
 
   public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
@@ -5822,7 +5827,6 @@
 
   public final class DeviceConfig {
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static float getFloat(@NonNull String, @NonNull String, float);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static int getInt(@NonNull String, @NonNull String, int);
@@ -5830,7 +5834,6 @@
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getProperty(@NonNull String, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_ACTIVITY_MANAGER = "activity_manager";
@@ -5863,10 +5866,6 @@
     method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
   }
 
-  public static interface DeviceConfig.OnPropertyChangedListener {
-    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
-  }
-
   public static class DeviceConfig.Properties {
     method public boolean getBoolean(@NonNull String, boolean);
     method public float getFloat(@NonNull String, float);
@@ -6274,7 +6273,6 @@
 
   public abstract class AttentionService extends android.app.Service {
     ctor public AttentionService();
-    method public final void disableSelf();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void onCancelAttentionCheck(@NonNull android.service.attention.AttentionService.AttentionCallback);
     method public abstract void onCheckAttention(@NonNull android.service.attention.AttentionService.AttentionCallback);
@@ -6395,9 +6393,9 @@
     method public void onConnected();
     method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
     method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+    method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
     method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDisconnected();
-    method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
     method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 5d74e17..8f71122 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -125,6 +125,19 @@
 
 }
 
+package android.provider {
+
+  public final class DeviceConfig {
+    method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+    method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+  }
+
+  public static interface DeviceConfig.OnPropertyChangedListener {
+    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+  }
+
+}
+
 package android.service.notification {
 
   public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index a0de7f3..f76b383 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -498,12 +498,13 @@
   }
 
   public static final class AppTarget.Builder {
-    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
+    ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
     method @NonNull public android.app.prediction.AppTarget build();
     method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
     method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
-    method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
   }
 
   public final class AppTargetEvent implements android.os.Parcelable {
@@ -1105,6 +1106,7 @@
     method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission("android.permission.MODIFY_AUDIO_ROUTING") public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+    field public static final int SUCCESS = 0; // 0x0
   }
 
   public static final class AudioRecord.MetricsConstants {
@@ -1130,22 +1132,6 @@
     field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
   }
 
-  public final class BufferingParams implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getInitialMarkMs();
-    method public int getResumePlaybackMarkMs();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
-  }
-
-  public static class BufferingParams.Builder {
-    ctor public BufferingParams.Builder();
-    ctor public BufferingParams.Builder(android.media.BufferingParams);
-    method public android.media.BufferingParams build();
-    method public android.media.BufferingParams.Builder setInitialMarkMs(int);
-    method public android.media.BufferingParams.Builder setResumePlaybackMarkMs(int);
-  }
-
   public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size);
     ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size);
@@ -1242,8 +1228,10 @@
     method public int detachMixes(@NonNull java.util.List<android.media.audiopolicy.AudioMix>);
     method public int getFocusDuckingBehavior();
     method public int getStatus();
+    method public boolean removeUidDeviceAffinity(int);
     method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setRegistration(String);
+    method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
     method public String toLogFriendlyString();
     field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
     field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
@@ -1460,9 +1448,6 @@
     method public static long getLoopbackRxPackets();
     method public static long getLoopbackTxBytes();
     method public static long getLoopbackTxPackets();
-    field public static final int TAG_SYSTEM_DHCP = -192; // 0xffffff40
-    field public static final int TAG_SYSTEM_DHCP_SERVER = -186; // 0xffffff46
-    field public static final int TAG_SYSTEM_PROBE = -190; // 0xffffff42
   }
 
 }
@@ -2213,7 +2198,6 @@
 
   public final class DeviceConfig {
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertiesChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static boolean getBoolean(@NonNull String, @NonNull String, boolean);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static float getFloat(@NonNull String, @NonNull String, float);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static int getInt(@NonNull String, @NonNull String, int);
@@ -2221,7 +2205,6 @@
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(@NonNull String, @NonNull String);
     method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getString(@NonNull String, @NonNull String, @Nullable String);
     method public static void removeOnPropertiesChangedListener(@NonNull android.provider.DeviceConfig.OnPropertiesChangedListener);
-    method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
     field public static final String NAMESPACE_AUTOFILL = "autofill";
@@ -2235,10 +2218,6 @@
     method public void onPropertiesChanged(@NonNull android.provider.DeviceConfig.Properties);
   }
 
-  public static interface DeviceConfig.OnPropertyChangedListener {
-    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
-  }
-
   public static class DeviceConfig.Properties {
     method public boolean getBoolean(@NonNull String, boolean);
     method public float getFloat(@NonNull String, float);
@@ -2552,9 +2531,9 @@
     method public void onConnected();
     method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
     method public void onCreateContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext, @NonNull android.view.contentcapture.ContentCaptureSessionId);
+    method public void onDataRemovalRequest(@NonNull android.view.contentcapture.DataRemovalRequest);
     method public void onDestroyContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureSessionId);
     method public void onDisconnected();
-    method public void onUserDataRemovalRequest(@NonNull android.view.contentcapture.UserDataRemovalRequest);
     method public final void setContentCaptureConditions(@NonNull String, @Nullable java.util.Set<android.view.contentcapture.ContentCaptureCondition>);
     method public final void setContentCaptureWhitelist(@Nullable java.util.Set<java.lang.String>, @Nullable java.util.Set<android.content.ComponentName>);
     field public static final String SERVICE_INTERFACE = "android.service.contentcapture.ContentCaptureService";
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d802177..83a5708 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1 +1,14 @@
 // Signature format: 2.0
+package android.provider {
+
+  public final class DeviceConfig {
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static void addOnPropertyChangedListener(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+    method public static void removeOnPropertyChangedListener(@NonNull android.provider.DeviceConfig.OnPropertyChangedListener);
+  }
+
+  public static interface DeviceConfig.OnPropertyChangedListener {
+    method public void onPropertyChanged(@NonNull String, @NonNull String, @Nullable String);
+  }
+
+}
+
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 47617e0..bb8d927 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -16,6 +16,7 @@
 
 #include <sys/stat.h>   // umask
 #include <sys/types.h>  // umask
+
 #include <fstream>
 #include <memory>
 #include <ostream>
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 677c6fa..b7ae9d0 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -31,15 +31,14 @@
 #include "androidfw/ResourceUtils.h"
 #include "androidfw/StringPiece.h"
 #include "androidfw/Util.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 #include "idmap2/Xml.h"
 #include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
 
 using android::ApkAssets;
 using android::ApkAssetsCookie;
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index d8867fe..8794908 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -23,12 +23,11 @@
 #include <string>
 #include <vector>
 
+#include "Commands.h"
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 
-#include "Commands.h"
-
 using android::idmap2::CommandLineOptions;
 using android::idmap2::Result;
 using android::idmap2::Unit;
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 55b1003..fa9a77a 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <dirent.h>
+
 #include <fstream>
 #include <memory>
 #include <ostream>
@@ -24,8 +25,8 @@
 #include <utility>
 #include <vector>
 
+#include "Commands.h"
 #include "android-base/properties.h"
-
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
@@ -35,8 +36,6 @@
 #include "idmap2/Xml.h"
 #include "idmap2/ZipFile.h"
 
-#include "Commands.h"
-
 using android::idmap2::CommandLineOptions;
 using android::idmap2::Error;
 using android::idmap2::Idmap;
@@ -211,7 +210,9 @@
 
       const auto create_ok = Create(create_args);
       if (!create_ok) {
-        return Error(create_ok.GetError(), "failed to create idmap");
+        LOG(WARNING) << "failed to create idmap for overlay apk path \"" << overlay.apk_path
+                     << "\": " << create_ok.GetError().GetMessage();
+        continue;
       }
     }
 
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 4f65379..8ee79f6 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "idmap2d/Idmap2Service.h"
+
 #include <sys/stat.h>   // umask
 #include <sys/types.h>  // umask
 #include <unistd.h>
@@ -28,15 +30,12 @@
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
 #include "binder/IPCThreadState.h"
-#include "utils/String8.h"
-
 #include "idmap2/BinaryStreamVisitor.h"
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/Policies.h"
 #include "idmap2/SysTrace.h"
-
-#include "idmap2d/Idmap2Service.h"
+#include "utils/String8.h"
 
 using android::IPCThreadState;
 using android::binder::Status;
diff --git a/cmds/idmap2/idmap2d/Main.cpp b/cmds/idmap2/idmap2d/Main.cpp
index 4393dcc..2707049 100644
--- a/cmds/idmap2/idmap2d/Main.cpp
+++ b/cmds/idmap2/idmap2d/Main.cpp
@@ -21,13 +21,11 @@
 #include <binder/ProcessState.h>
 
 #include <cstdlib>  // EXIT_{FAILURE,SUCCESS}
-
 #include <iostream>
 #include <sstream>
 
-#include "android-base/macros.h"
-
 #include "Idmap2Service.h"
+#include "android-base/macros.h"
 
 using android::BinderService;
 using android::IPCThreadState;
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index 5cc0664b..ebbb5ffc 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -52,11 +52,9 @@
 #include <vector>
 
 #include "android-base/macros.h"
-
 #include "androidfw/ApkAssets.h"
 #include "androidfw/ResourceTypes.h"
 #include "androidfw/StringPiece.h"
-
 #include "idmap2/Policies.h"
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
index cd76b84..90c698c 100644
--- a/cmds/idmap2/include/idmap2/Policies.h
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -17,11 +17,10 @@
 #include <string>
 #include <vector>
 
+#include "Result.h"
 #include "androidfw/ResourceTypes.h"
 #include "androidfw/StringPiece.h"
 
-#include "Result.h"
-
 #ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
 #define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
 
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index c388f4b..5111bb2 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -21,7 +21,6 @@
 #include <memory>
 
 #include "androidfw/AssetManager2.h"
-
 #include "idmap2/Idmap.h"
 
 namespace android {
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 7e33b3b..2e543d4 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -22,7 +22,6 @@
 #include <string>
 
 #include "androidfw/AssetManager2.h"
-
 #include "idmap2/Idmap.h"
 
 namespace android {
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
index 1d81c48..8797a78 100644
--- a/cmds/idmap2/include/idmap2/ResourceUtils.h
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -21,7 +21,6 @@
 #include <string>
 
 #include "androidfw/AssetManager2.h"
-
 #include "idmap2/Idmap.h"
 #include "idmap2/Result.h"
 #include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 9651328..dee2d21 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
+#include "idmap2/BinaryStreamVisitor.h"
+
 #include <algorithm>
 #include <cstring>
 #include <string>
 
 #include "android-base/macros.h"
 
-#include "idmap2/BinaryStreamVisitor.h"
-
 namespace android::idmap2 {
 
 void BinaryStreamVisitor::Write16(uint16_t value) {
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index d5fd2ce..5b0ae92 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "idmap2/CommandLineOptions.h"
+
 #include <algorithm>
 #include <iomanip>
 #include <iostream>
@@ -24,8 +26,6 @@
 #include <vector>
 
 #include "android-base/macros.h"
-
-#include "idmap2/CommandLineOptions.h"
 #include "idmap2/Result.h"
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index a9b68cd..3e8e329 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "idmap2/FileUtils.h"
+
 #include <dirent.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -33,8 +35,6 @@
 #include "android-base/stringprintf.h"
 #include "private/android_filesystem_config.h"
 
-#include "idmap2/FileUtils.h"
-
 namespace android::idmap2::utils {
 
 std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 49470b4..aec1a6f 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "idmap2/Idmap.h"
+
 #include <algorithm>
 #include <iostream>
 #include <iterator>
@@ -28,14 +30,12 @@
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/AssetManager2.h"
-#include "utils/String16.h"
-#include "utils/String8.h"
-
-#include "idmap2/Idmap.h"
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 #include "idmap2/ZipFile.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
 
 namespace android::idmap2 {
 
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index 7c45556..0a0cecf 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
+#include "idmap2/Policies.h"
+
 #include <iterator>
 #include <map>
 #include <string>
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
-
 #include "idmap2/Idmap.h"
-#include "idmap2/Policies.h"
 #include "idmap2/Result.h"
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fc967799..fbf2c77 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
+#include "idmap2/PrettyPrintVisitor.h"
+
 #include <string>
 
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/ApkAssets.h"
-
-#include "idmap2/PrettyPrintVisitor.h"
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 1149c90..dd14fd4 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
+#include "idmap2/RawPrintVisitor.h"
+
 #include <cstdarg>
 #include <string>
 
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/ApkAssets.h"
-
-#include "idmap2/RawPrintVisitor.h"
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
index a24836d..71ba3f0 100644
--- a/cmds/idmap2/libidmap2/ResourceUtils.cpp
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
+#include "idmap2/ResourceUtils.h"
+
 #include <memory>
 #include <string>
 
 #include "androidfw/StringPiece.h"
 #include "androidfw/Util.h"
-
-#include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 #include "idmap2/Xml.h"
 #include "idmap2/ZipFile.h"
diff --git a/cmds/idmap2/libidmap2/Result.cpp b/cmds/idmap2/libidmap2/Result.cpp
index 471dab2..1eac25f 100644
--- a/cmds/idmap2/libidmap2/Result.cpp
+++ b/cmds/idmap2/libidmap2/Result.cpp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
+#include "idmap2/Result.h"
+
 #include <cstdarg>
 
 #include "android-base/stringprintf.h"
 
-#include "idmap2/Result.h"
-
 namespace android::idmap2 {
 
 // NOLINTNEXTLINE(cert-dcl50-cpp)
diff --git a/cmds/idmap2/libidmap2/Xml.cpp b/cmds/idmap2/libidmap2/Xml.cpp
index 0075a92..2645868 100644
--- a/cmds/idmap2/libidmap2/Xml.cpp
+++ b/cmds/idmap2/libidmap2/Xml.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
+#include "idmap2/Xml.h"
+
 #include <map>
 #include <memory>
 #include <string>
 #include <utility>
 
-#include "idmap2/Xml.h"
-
 namespace android::idmap2 {
 
 std::unique_ptr<const Xml> Xml::Create(const uint8_t* data, size_t size, bool copyData) {
diff --git a/cmds/idmap2/libidmap2/ZipFile.cpp b/cmds/idmap2/libidmap2/ZipFile.cpp
index 0f07324..812fd6e 100644
--- a/cmds/idmap2/libidmap2/ZipFile.cpp
+++ b/cmds/idmap2/libidmap2/ZipFile.cpp
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
+#include "idmap2/ZipFile.h"
+
 #include <memory>
 #include <string>
 
 #include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
 
 namespace android::idmap2 {
 
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 9a5b633..9cdc86c 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -19,17 +19,14 @@
 #include <string>
 #include <utility>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "idmap2/BinaryStreamVisitor.h"
 #include "idmap2/Idmap.h"
 
-#include "TestHelpers.h"
-
 using ::testing::NotNull;
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index d567af6..6e83fc9 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -25,19 +25,16 @@
 #include <string>
 #include <vector>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
 #include "android-base/file.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/Idmap.h"
 #include "androidfw/LoadedArsc.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
 
-#include "TestHelpers.h"
-
 namespace android::idmap2 {
 
 TEST(CommandLineOptionsTests, Flag) {
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 34a0097..f4a306e 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -15,19 +15,17 @@
  */
 
 #include <dirent.h>
+
 #include <set>
 #include <string>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
 #include "android-base/macros.h"
 #include "android-base/stringprintf.h"
-#include "private/android_filesystem_config.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "idmap2/FileUtils.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
 
 using ::testing::NotNull;
 
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 91bc4dd..c18744c 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -34,16 +34,13 @@
 #include <string>
 #include <vector>
 
+#include "TestHelpers.h"
+#include "androidfw/PosixUtils.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-#include "androidfw/PosixUtils.h"
-#include "private/android_filesystem_config.h"
-
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
-
-#include "TestHelpers.h"
+#include "private/android_filesystem_config.h"
 
 using ::android::util::ExecuteBinary;
 using ::testing::NotNull;
@@ -264,6 +261,24 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   ASSERT_EQ(result->stdout, "");
+
+  // the signature idmap failing to generate should not cause scanning to fail
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "scan",
+                          "--input-directory", GetTestDataPath(),
+                          "--recursive",
+                          "--target-package-name", "test.target",
+                          "--target-apk-path", GetTargetApkPath(),
+                          "--output-directory", GetTempDirPath(),
+                          "--override-policy", "public"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->stdout, expected.str());
+  unlink(idmap_static_no_name_path.c_str());
+  unlink(idmap_static_2_path.c_str());
+  unlink(idmap_static_1_path.c_str());
 }
 
 TEST_F(Idmap2BinaryTests, Lookup) {
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 621f503..90fe9a7 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -15,7 +15,6 @@
  */
 
 #include <cstdio>  // fclose
-
 #include <fstream>
 #include <memory>
 #include <sstream>
@@ -23,18 +22,15 @@
 #include <utility>
 #include <vector>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
 #include "android-base/macros.h"
 #include "androidfw/ApkAssets.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "idmap2/BinaryStreamVisitor.h"
 #include "idmap2/CommandLineOptions.h"
 #include "idmap2/Idmap.h"
 
-#include "TestHelpers.h"
-
 using ::testing::IsNull;
 using ::testing::NotNull;
 
diff --git a/cmds/idmap2/tests/Main.cpp b/cmds/idmap2/tests/Main.cpp
index 2b13fed..3e753e9 100644
--- a/cmds/idmap2/tests/Main.cpp
+++ b/cmds/idmap2/tests/Main.cpp
@@ -16,11 +16,9 @@
 
 #include <string>
 
-#include "android-base/file.h"
-
-#include "gtest/gtest.h"
-
 #include "TestHelpers.h"
+#include "android-base/file.h"
+#include "gtest/gtest.h"
 
 namespace android::idmap2 {
 
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
index a76da53..e30da76 100644
--- a/cmds/idmap2/tests/PoliciesTests.cpp
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -16,9 +16,8 @@
 
 #include <string>
 
-#include "gtest/gtest.h"
-
 #include "TestHelpers.h"
+#include "gtest/gtest.h"
 #include "idmap2/Policies.h"
 
 using android::idmap2::PolicyBitmask;
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 27a3880..c412504 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -18,18 +18,15 @@
 #include <sstream>
 #include <string>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
+#include "TestHelpers.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/Idmap.h"
-
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "idmap2/Idmap.h"
 #include "idmap2/Policies.h"
 #include "idmap2/PrettyPrintVisitor.h"
 
-#include "TestHelpers.h"
-
 using ::testing::NotNull;
 
 using android::ApkAssets;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 7372148..64518fd 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -19,14 +19,12 @@
 #include <sstream>
 #include <string>
 
+#include "TestHelpers.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
 #include "idmap2/Idmap.h"
 #include "idmap2/RawPrintVisitor.h"
 
-#include "TestHelpers.h"
-
 using ::testing::NotNull;
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index ad78685..9ed807c 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -17,15 +17,13 @@
 #include <memory>
 #include <string>
 
+#include "TestHelpers.h"
+#include "androidfw/ApkAssets.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-#include "androidfw/ApkAssets.h"
 #include "idmap2/ResourceUtils.h"
 #include "idmap2/Result.h"
 
-#include "TestHelpers.h"
-
 using ::testing::NotNull;
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/ResultTests.cpp b/cmds/idmap2/tests/ResultTests.cpp
index 5f4daed..cbced0a 100644
--- a/cmds/idmap2/tests/ResultTests.cpp
+++ b/cmds/idmap2/tests/ResultTests.cpp
@@ -20,7 +20,6 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
 #include "idmap2/Result.h"
 
 namespace android::idmap2 {
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 45525a5..adea329 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -19,6 +19,9 @@
 
 #include <string>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
 namespace android::idmap2 {
 
 const unsigned char idmap_raw_data[] = {
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
index fe79d8f..df63211 100644
--- a/cmds/idmap2/tests/XmlTests.cpp
+++ b/cmds/idmap2/tests/XmlTests.cpp
@@ -16,13 +16,11 @@
 
 #include <cstdio>  // fclose
 
-#include "idmap2/Xml.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
 
 using ::testing::IsNull;
 using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
index 79be43c..3fca436 100644
--- a/cmds/idmap2/tests/ZipFileTests.cpp
+++ b/cmds/idmap2/tests/ZipFileTests.cpp
@@ -17,13 +17,11 @@
 #include <cstdio>  // fclose
 #include <string>
 
-#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
-
+#include "TestHelpers.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-#include "TestHelpers.h"
+#include "idmap2/Result.h"
+#include "idmap2/ZipFile.h"
 
 using ::testing::IsNull;
 using ::testing::NotNull;
diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
index 9e6a453..5df0bea 100644
--- a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
@@ -19,5 +19,7 @@
     <application android:hasCode="false"/>
     <overlay
         android:targetPackage="test.target"
-        android:targetName="TestResources"/>
+        android:targetName="TestResources"
+        android:isStatic="true"
+        android:priority="10"/>
 </manifest>
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
index b2c490d..51e19de 100644
--- a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 55d3fba..d28108c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -268,7 +268,8 @@
         TouchGestureClassified touch_gesture_classified = 177;
         HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
         StyleUIChanged style_ui_changed = 179;
-        PrivacyIndicatorsInteracted privacy_indicators_interacted = 180;
+        PrivacyIndicatorsInteracted privacy_indicators_interacted =
+	    180 [(log_from_module) = "permissioncontroller"];
         AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
         NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
         AppMovedStorageReported app_moved_storage_reported = 183;
@@ -340,6 +341,7 @@
         SystemIonHeapSize system_ion_heap_size = 10056;
         AppsOnExternalStorageInfo apps_on_external_storage_info = 10057;
         FaceSettings face_settings = 10058;
+        CoolingDevice cooling_device = 10059;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -410,17 +412,25 @@
  *   frameworks/base/services/core/java/com/android/server/stats/StatsCompanionService.java
  */
 message ThermalThrottlingStateChanged {
+    // The type of temperature being reported (CPU, GPU, SKIN, etc)
     optional android.os.TemperatureTypeEnum sensor_type = 1;
 
+    // Throttling state, this field is DEPRECATED
     enum State {
         UNKNOWN = 0;
-        START = 1;
-        STOP = 2;
+        START = 1; // START indicated that throttling was triggered.
+        STOP = 2; // STOP indicates that throttling was cleared.
     }
-
     optional State state = 2;
 
+    // Temperature in deci degrees celsius
     optional float temperature = 3;
+
+    // Severity of throttling
+    optional android.os.ThrottlingSeverityEnum severity = 4;
+
+    // Thermistor name
+    optional string sensor_name = 5;
 }
 
 /**
@@ -3957,8 +3967,7 @@
  * Pulls the temperature of various parts of the device.
  * The units are tenths of a degree Celsius. Eg: 30.3C is reported as 303.
  *
- * Pulled from:
- *   frameworks/base/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
+ * Pulled from StatsCompanionService.java
  */
 message Temperature {
     // The type of temperature being reported. Eg. CPU, GPU, SKIN, BATTERY, BCL_.
@@ -3970,6 +3979,9 @@
     // Temperature in tenths of a degree C.
     // For BCL, it is decimillivolt, decimilliamps, and percentage * 10.
     optional int32 temperature_deci_celsius = 3;
+
+    // Relative severity of the throttling, see enum definition.
+    optional android.os.ThrottlingSeverityEnum severity = 4;
 }
 
 /**
@@ -5947,3 +5959,19 @@
     // Whether or not a diverse set of poses are required during enrollment.
     optional bool unlock_diversity_required = 6;
 }
+
+/**
+ * Logs cooling devices maintained by the kernel.
+ *
+ * Pulled from StatsCompanionService.java
+ */
+message CoolingDevice {
+    // The type of cooling device being reported. Eg. CPU, GPU...
+    optional android.os.CoolingTypeEnum device_location = 1;
+    // The name of the cooling device source. Eg. CPU0
+    optional string device_name = 2;
+    // Current throttle state of the cooling device. The value can any unsigned
+    // integer between 0 and max_state defined in its driver. 0 means device is
+    // not in throttling, higher value means deeper throttling.
+    optional int32 state = 3;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 51839c4..ca73059 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -159,6 +159,9 @@
         // temperature
         {android::util::TEMPERATURE,
          {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
+        // cooling_device
+        {android::util::COOLING_DEVICE,
+         {.puller = new StatsCompanionServicePuller(android::util::COOLING_DEVICE)}},
         // binder_calls
         {android::util::BINDER_CALLS,
          {.additiveFields = {4, 5, 6, 8, 12},
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5f972c9..6e935e1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,7 +127,6 @@
 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;
@@ -724,7 +723,7 @@
         Window.Callback, KeyEvent.Callback,
         OnCreateContextMenuListener, ComponentCallbacks2,
         Window.OnWindowDismissedCallback, WindowControllerCallback,
-        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
+        AutofillManager.AutofillClient {
     private static final String TAG = "Activity";
     private static final boolean DEBUG_LIFECYCLE = false;
 
@@ -1124,12 +1123,6 @@
         return this;
     }
 
-    /** @hide */
-    @Override
-    public final ContentCaptureClient getContentCaptureClient() {
-        return this;
-    }
-
     /**
      * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
      * lifecycle callbacks for only this Activity.
@@ -6509,12 +6502,6 @@
         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
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 143361f..5e5611b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -27,6 +28,8 @@
 import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
 import static android.view.Display.INVALID_DISPLAY;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
@@ -193,6 +196,7 @@
 import java.util.Objects;
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
 
 final class RemoteServiceException extends AndroidRuntimeException {
     public RemoteServiceException(String msg) {
@@ -225,6 +229,11 @@
     public static final boolean DEBUG_ORDER = false;
     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
     /**
+     * If the activity doesn't become idle in time, the timeout will ensure to apply the pending top
+     * process state.
+     */
+    private static final long PENDING_TOP_PROCESS_STATE_TIMEOUT = 1000;
+    /**
      * The delay to release the provider when it has no more references. It reduces the number of
      * transactions for acquiring and releasing provider if the client accesses the provider
      * frequently in a short time.
@@ -242,6 +251,11 @@
     // Whether to invoke an activity callback after delivering new configuration.
     private static final boolean REPORT_TO_ACTIVITY = true;
 
+    /** Use foreground GC policy (less pause time) and higher JIT weight. */
+    private static final int VM_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
+    /** Use background GC policy and default JIT threshold. */
+    private static final int VM_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
+
     /**
      * Denotes an invalid sequence number corresponding to a process state change.
      */
@@ -296,6 +310,11 @@
     // Number of activities that are currently visible on-screen.
     @UnsupportedAppUsage
     int mNumVisibleActivities = 0;
+    private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
+    @GuardedBy("mAppThread")
+    private int mLastProcessState = PROCESS_STATE_UNKNOWN;
+    @GuardedBy("mAppThread")
+    private int mPendingProcessState = PROCESS_STATE_UNKNOWN;
     ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
     private int mLastSessionId;
     @UnsupportedAppUsage
@@ -873,17 +892,6 @@
     private class ApplicationThread extends IApplicationThread.Stub {
         private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
 
-        private int mLastProcessState = -1;
-
-        private void updatePendingConfiguration(Configuration config) {
-            synchronized (mResourcesManager) {
-                if (mPendingConfiguration == null ||
-                        mPendingConfiguration.isOtherSeqNewer(config)) {
-                    mPendingConfiguration = config;
-                }
-            }
-        }
-
         public final void scheduleSleeping(IBinder token, boolean sleeping) {
             sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
         }
@@ -1560,27 +1568,6 @@
             updateProcessState(state, true);
         }
 
-        public void updateProcessState(int processState, boolean fromIpc) {
-            synchronized (this) {
-                if (mLastProcessState != processState) {
-                    mLastProcessState = processState;
-                    // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
-                    final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
-                    final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
-                    int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
-                    // TODO: Tune this since things like gmail sync are important background but not jank perceptible.
-                    if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                        dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
-                    }
-                    VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
-                    if (false) {
-                        Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
-                                + (fromIpc ? " (from ipc": ""));
-                    }
-                }
-            }
-        }
-
         /**
          * Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
          * the main thread that it needs to wait for the network rules to get updated before
@@ -1661,16 +1648,6 @@
         }
     }
 
-    @Override
-    public void updatePendingConfiguration(Configuration config) {
-        mAppThread.updatePendingConfiguration(config);
-    }
-
-    @Override
-    public void updateProcessState(int processState, boolean fromIpc) {
-        mAppThread.updateProcessState(processState, fromIpc);
-    }
-
     class H extends Handler {
         public static final int BIND_APPLICATION        = 110;
         @UnsupportedAppUsage
@@ -1995,6 +1972,7 @@
             if (stopProfiling) {
                 mProfiler.stopProfiling();
             }
+            applyPendingProcessState();
             return false;
         }
     }
@@ -2939,6 +2917,68 @@
         return mActivities.get(token);
     }
 
+    @Override
+    public void updatePendingConfiguration(Configuration config) {
+        synchronized (mResourcesManager) {
+            if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(config)) {
+                mPendingConfiguration = config;
+            }
+        }
+    }
+
+    @Override
+    public void updateProcessState(int processState, boolean fromIpc) {
+        synchronized (mAppThread) {
+            if (mLastProcessState == processState) {
+                return;
+            }
+            mLastProcessState = processState;
+            // Defer the top state for VM to avoid aggressive JIT compilation affecting activity
+            // launch time.
+            if (processState == ActivityManager.PROCESS_STATE_TOP
+                    && mNumLaunchingActivities.get() > 0) {
+                mPendingProcessState = processState;
+                mH.postDelayed(this::applyPendingProcessState, PENDING_TOP_PROCESS_STATE_TIMEOUT);
+            } else {
+                mPendingProcessState = PROCESS_STATE_UNKNOWN;
+                updateVmProcessState(processState);
+            }
+            if (localLOGV) {
+                Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
+                        + (fromIpc ? " (from ipc" : ""));
+            }
+        }
+    }
+
+    /** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
+    private void updateVmProcessState(int processState) {
+        // TODO: Tune this since things like gmail sync are important background but not jank
+        // perceptible.
+        final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+                ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
+                : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
+        VMRuntime.getRuntime().updateProcessState(state);
+    }
+
+    private void applyPendingProcessState() {
+        synchronized (mAppThread) {
+            if (mPendingProcessState == PROCESS_STATE_UNKNOWN) {
+                return;
+            }
+            final int pendingState = mPendingProcessState;
+            mPendingProcessState = PROCESS_STATE_UNKNOWN;
+            // Only apply the pending state if the last state doesn't change.
+            if (pendingState == mLastProcessState) {
+                updateVmProcessState(pendingState);
+            }
+        }
+    }
+
+    @Override
+    public void countLaunchingActivities(int num) {
+        mNumLaunchingActivities.getAndAdd(num);
+    }
+
     @UnsupportedAppUsage
     public final void sendActivityResult(
             IBinder token, String id, int requestCode,
@@ -4509,7 +4549,7 @@
         if (!show && !r.stopped) {
             performStopActivityInner(r, null /* stopInfo */, show, false /* saveState */,
                     false /* finalStateRequest */, "handleWindowVisibility");
-        } else if (show && r.stopped) {
+        } else if (show && r.getLifecycleState() == ON_STOP) {
             // If we are getting ready to gc after going to the background, well
             // we are back active so skip it.
             unscheduleGcIdler();
@@ -4570,7 +4610,7 @@
     private void onCoreSettingsChange() {
         if (updateDebugViewAttributeState()) {
             // request all activities to relaunch for the changes to take place
-            relaunchAllActivities();
+            relaunchAllActivities(false /* preserveWindows */);
         }
     }
 
@@ -4587,10 +4627,13 @@
         return previousState != View.sDebugViewAttributes;
     }
 
-    private void relaunchAllActivities() {
+    private void relaunchAllActivities(boolean preserveWindows) {
         for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
-            final Activity activity = entry.getValue().activity;
-            if (!activity.mFinished) {
+            final ActivityClientRecord r = entry.getValue();
+            if (!r.activity.mFinished) {
+                if (preserveWindows && r.window != null) {
+                    r.mPreserveWindow = true;
+                }
                 scheduleRelaunchActivity(entry.getKey());
             }
         }
@@ -5423,7 +5466,8 @@
         }
     }
 
-    void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
+    @VisibleForTesting(visibility = PACKAGE)
+    public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
         // Updates triggered by package installation go through a package update
         // receiver. Here we try to capture ApplicationInfo changes that are
         // caused by other sources, such as overlays. That means we want to be as conservative
@@ -5469,7 +5513,8 @@
         newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
         handleConfigurationChanged(newConfig, null);
 
-        relaunchAllActivities();
+        // Preserve windows to avoid black flickers when overlays change.
+        relaunchAllActivities(true /* preserveWindows */);
     }
 
     static void freeTextLayoutCachesIfNeeded(int configDiff) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6f92244..227703d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -823,9 +823,11 @@
     public static final int OP_LEGACY_STORAGE = 87;
     /** @hide Accessing accessibility features */
     public static final int OP_ACCESS_ACCESSIBILITY = 88;
+    /** @hide Read the device identifiers (IMEI / MEID, IMSI, SIM / Build serial) */
+    public static final int OP_READ_DEVICE_IDENTIFIERS = 89;
     /** @hide */
     @UnsupportedAppUsage
-    public static final int _NUM_OP = 89;
+    public static final int _NUM_OP = 90;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1099,6 +1101,8 @@
     /** @hide Interact with accessibility. */
     @SystemApi
     public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
+    /** @hide Read device identifiers */
+    public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
 
     // Warning: If an permission is added here it also has to be added to
     // com.android.packageinstaller.permission.utils.EventLogger
@@ -1259,6 +1263,7 @@
             OP_WRITE_MEDIA_IMAGES,              // WRITE_MEDIA_IMAGES
             OP_LEGACY_STORAGE,                  // LEGACY_STORAGE
             OP_ACCESS_ACCESSIBILITY,            // ACCESS_ACCESSIBILITY
+            OP_READ_DEVICE_IDENTIFIERS,         // READ_DEVICE_IDENTIFIERS
     };
 
     /**
@@ -1354,6 +1359,7 @@
             OPSTR_WRITE_MEDIA_IMAGES,
             OPSTR_LEGACY_STORAGE,
             OPSTR_ACCESS_ACCESSIBILITY,
+            OPSTR_READ_DEVICE_IDENTIFIERS,
     };
 
     /**
@@ -1450,6 +1456,7 @@
             "WRITE_MEDIA_IMAGES",
             "LEGACY_STORAGE",
             "ACCESS_ACCESSIBILITY",
+            "READ_DEVICE_IDENTIFIERS",
     };
 
     /**
@@ -1547,6 +1554,7 @@
             null, // no permission for OP_WRITE_MEDIA_IMAGES
             null, // no permission for OP_LEGACY_STORAGE
             null, // no permission for OP_ACCESS_ACCESSIBILITY
+            null, // no direct permission for OP_READ_DEVICE_IDENTIFIERS
     };
 
     /**
@@ -1644,6 +1652,7 @@
             null, // WRITE_MEDIA_IMAGES
             null, // LEGACY_STORAGE
             null, // ACCESS_ACCESSIBILITY
+            null, // READ_DEVICE_IDENTIFIERS
     };
 
     /**
@@ -1740,6 +1749,7 @@
             false, // WRITE_MEDIA_IMAGES
             false, // LEGACY_STORAGE
             false, // ACCESS_ACCESSIBILITY
+            false, // READ_DEVICE_IDENTIFIERS
     };
 
     /**
@@ -1835,6 +1845,7 @@
             AppOpsManager.MODE_ERRORED, // WRITE_MEDIA_IMAGES
             AppOpsManager.MODE_DEFAULT, // LEGACY_STORAGE
             AppOpsManager.MODE_ALLOWED, // ACCESS_ACCESSIBILITY
+            AppOpsManager.MODE_ERRORED, // READ_DEVICE_IDENTIFIERS
     };
 
     /**
@@ -1934,6 +1945,7 @@
             false, // WRITE_MEDIA_IMAGES
             false, // LEGACY_STORAGE
             false, // ACCESS_ACCESSIBILITY
+            false, // READ_DEVICE_IDENTIFIERS
     };
 
     /**
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 9dc8b45..d308adc 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -78,6 +78,8 @@
     /** Set current process state. */
     public abstract void updateProcessState(int processState, boolean fromIpc);
 
+    /** Count how many activities are launching. */
+    public abstract void countLaunchingActivities(int num);
 
     // Execute phase related logic and handlers. Methods here execute actual lifecycle transactions
     // and deliver callbacks.
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 14c58e7..def1f45 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -27,5 +27,15 @@
                 }
             ]
         }
+    ],
+    "postsubmit": [
+        {
+            "file_patterns": ["(/|^)ActivityThreadClientTest.java"],
+            "name": "FrameworksMockingCoreTests"
+        },
+        {
+            "file_patterns": ["(/|^)ActivityThreadTest.java"],
+            "name": "FrameworksCoreTests"
+        }
     ]
 }
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index dd00e5a..de64db9 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -58,23 +60,27 @@
      * The base intent of the task (generally the intent that launched the task). This intent can
      * be used to relaunch the task (if it is no longer running) or brought to the front if it is.
      */
+    @NonNull
     public Intent baseIntent;
 
     /**
      * The component of the first activity in the task, can be considered the "application" of this
      * task.
      */
+    @Nullable
     public ComponentName baseActivity;
 
     /**
      * The component of the top activity in the task, currently showing to the user.
      */
+    @Nullable
     public ComponentName topActivity;
 
     /**
      * The component of the target activity if this task was started from an activity alias.
      * Otherwise, this is null.
      */
+    @Nullable
     public ComponentName origActivity;
 
     /**
@@ -82,6 +88,7 @@
      * alias).
      * @hide
      */
+    @Nullable
     public ComponentName realActivity;
 
     /**
@@ -106,6 +113,7 @@
      * The recent activity values for the highest activity in the stack to have set the values.
      * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
      */
+    @Nullable
     public ActivityManager.TaskDescription taskDescription;
 
     /**
@@ -126,6 +134,7 @@
      * The current configuration of the task.
      * @hide
      */
+    @NonNull
     @UnsupportedAppUsage
     public final Configuration configuration = new Configuration();
 
diff --git a/core/java/android/app/Vr2dDisplayProperties.java b/core/java/android/app/Vr2dDisplayProperties.java
index bcb8592..fc200bf 100644
--- a/core/java/android/app/Vr2dDisplayProperties.java
+++ b/core/java/android/app/Vr2dDisplayProperties.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -136,7 +137,7 @@
     /**
      * Prints out dump info.
      */
-    public void dump(PrintWriter pw, String prefix) {
+    public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
         pw.println(prefix + toString());
     }
 
@@ -188,7 +189,7 @@
     /**
      * Convenience class for creating Vr2dDisplayProperties.
      */
-    public static class Builder {
+    public static final class Builder {
         private int mAddedFlags = 0;
         private int mRemovedFlags = 0;
 
@@ -203,6 +204,7 @@
         /**
          * Sets the dimensions to use for the virtual display.
          */
+        @NonNull
         public Builder setDimensions(int width, int height, int dpi) {
             mWidth = width;
             mHeight = height;
@@ -213,6 +215,7 @@
         /**
          * Toggles the virtual display functionality for 2D activities in VR.
          */
+        @NonNull
         public Builder setEnabled(boolean enabled) {
             if (enabled) {
                 addFlags(FLAG_VIRTUAL_DISPLAY_ENABLED);
@@ -225,6 +228,7 @@
         /**
          * Adds property flags.
          */
+        @NonNull
         public Builder addFlags(@Vr2dDisplayFlag int flags) {
             mAddedFlags |= flags;
             mRemovedFlags &= ~flags;
@@ -234,6 +238,7 @@
         /**
          * Removes property flags.
          */
+        @NonNull
         public Builder removeFlags(@Vr2dDisplayFlag int flags) {
             mRemovedFlags |= flags;
             mAddedFlags &= ~flags;
@@ -243,6 +248,7 @@
         /**
          * Builds the Vr2dDisplayProperty instance.
          */
+        @NonNull
         public Vr2dDisplayProperties build() {
             return new Vr2dDisplayProperties(mWidth, mHeight, mDpi, mAddedFlags, mRemovedFlags);
         }
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 5f1a94c..c74f8c3 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -2,6 +2,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -71,7 +72,7 @@
             android.Manifest.permission.ACCESS_VR_STATE
     })
     public void registerVrStateCallback(@NonNull @CallbackExecutor Executor executor,
-            VrStateCallback callback) {
+            @NonNull VrStateCallback callback) {
         if (callback == null || mCallbackMap.containsKey(callback)) {
             return;
         }
@@ -99,7 +100,7 @@
             android.Manifest.permission.RESTRICTED_VR_ACCESS,
             android.Manifest.permission.ACCESS_VR_STATE
     })
-    public void unregisterVrStateCallback(VrStateCallback callback) {
+    public void unregisterVrStateCallback(@NonNull VrStateCallback callback) {
         CallbackEntry entry = mCallbackMap.remove(callback);
         if (entry != null) {
             try {
@@ -175,7 +176,7 @@
      */
     @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public void setVr2dDisplayProperties(
-            Vr2dDisplayProperties vr2dDisplayProp) {
+            @NonNull Vr2dDisplayProperties vr2dDisplayProp) {
         try {
             mService.setVr2dDisplayProperties(vr2dDisplayProp);
         } catch (RemoteException e) {
@@ -220,7 +221,7 @@
      * @param componentName not used
      */
     @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
-    public void setVrInputMethod(ComponentName componentName) {
+    public void setVrInputMethod(@Nullable ComponentName componentName) {
     }
 
     /**
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index 3f2f209..cd635d6 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -271,7 +271,9 @@
             if (mCloseGuard != null) {
                 mCloseGuard.warnIfOpen();
             }
-            destroy();
+            if (!mIsClosed.get()) {
+                destroy();
+            }
         } finally {
             super.finalize();
         }
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index ed45b2f..61e4569 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -204,24 +204,49 @@
         private int mRank;
 
         /**
-         * @param id A unique id for this launchable target.
+         * @deprecated Use the other Builder constructors.
          * @hide
          */
+        @Deprecated
         @SystemApi
-        @TestApi
         public Builder(@NonNull AppTargetId id) {
             mId = id;
         }
 
         /**
-         * Sets the target to be an app.
-         *
-         * @param packageName PackageName of the app
+         * @param id A unique id for this launchable target.
+         * @param packageName PackageName of the target.
          * @param user The UserHandle of the user which this target belongs to.
-         *
-         * @throws IllegalArgumentException is the target is already set
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public Builder(@NonNull AppTargetId id, @NonNull String packageName,
+                @NonNull UserHandle user) {
+            mId = Preconditions.checkNotNull(id);
+            mPackageName = Preconditions.checkNotNull(packageName);
+            mUser = Preconditions.checkNotNull(user);
+        }
+
+        /**
+         * @param id A unique id for this launchable target.
+         * @param info The ShortcutInfo that represents this launchable target.
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
+            mId = Preconditions.checkNotNull(id);
+            mShortcutInfo = Preconditions.checkNotNull(info);
+            mPackageName = info.getPackage();
+            mUser = info.getUserHandle();
+        }
+
+        /**
+         * @deprecated Use the appropriate constructor.
          */
         @NonNull
+        @Deprecated
         public Builder setTarget(@NonNull String packageName, @NonNull UserHandle user) {
             if (mPackageName != null) {
                 throw new IllegalArgumentException("Target is already set");
@@ -232,11 +257,10 @@
         }
 
         /**
-         * Sets the target to be a ShortcutInfo.
-         *
-         * @throws IllegalArgumentException is the target is already set
+         * @deprecated Use the appropriate constructor.
          */
         @NonNull
+        @Deprecated
         public Builder setTarget(@NonNull ShortcutInfo info) {
             setTarget(info.getPackage(), info.getUserHandle());
             mShortcutInfo = Preconditions.checkNotNull(info);
@@ -244,7 +268,7 @@
         }
 
         /**
-         * Sets the className for the target
+         * Sets the className for the target.
          */
         @NonNull
         public Builder setClassName(@NonNull String className) {
@@ -253,7 +277,7 @@
         }
 
         /**
-         * Sets the rank of the for the target.
+         * Sets the rank of the target.
          */
         @NonNull
         public Builder setRank(@IntRange(from = 0) int rank) {
@@ -274,7 +298,7 @@
         @NonNull
         public AppTarget build() {
             if (mPackageName == null) {
-                throw new IllegalStateException("No target set");
+                throw new IllegalStateException("No target is set");
             }
             return new AppTarget(mId, mPackageName, mUser, mShortcutInfo, mClassName, mRank);
         }
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index 027e152..394a0d6 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -52,7 +52,10 @@
 
     private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
 
+    private static volatile ComponentName sRemoteServiceComponentName;
+
     private static final Object sRemoteServicesLock = new Object();
+
     /**
      * Global remote services (per user) used by all {@link RoleControllerManager managers}.
      */
@@ -62,18 +65,36 @@
     @NonNull
     private final RemoteService mRemoteService;
 
-    public RoleControllerManager(@NonNull Context context, @NonNull Handler handler) {
+    /**
+     * Initialize the remote service component name once so that we can avoid acquiring the
+     * PackageManagerService lock in constructor.
+     *
+     * @see #createWithInitializedRemoteServiceComponentName(Handler, Context)
+     */
+    public static void initializeRemoteServiceComponentName(@NonNull Context context) {
+        sRemoteServiceComponentName = getRemoteServiceComponentName(context);
+    }
+
+    /**
+     * Create a {@link RoleControllerManager} instance with the initialized remote service component
+     * name so that we can avoid acquiring the PackageManagerService lock in constructor.
+     *
+     * @see #initializeRemoteServiceComponentName(Context)
+     */
+    @NonNull
+    public static RoleControllerManager createWithInitializedRemoteServiceComponentName(
+            @NonNull Handler handler, @NonNull Context context) {
+        return new RoleControllerManager(sRemoteServiceComponentName, handler, context);
+    }
+
+    private RoleControllerManager(@NonNull ComponentName remoteServiceComponentName,
+            @NonNull Handler handler, @NonNull Context context) {
         synchronized (sRemoteServicesLock) {
             int userId = context.getUserId();
             RemoteService remoteService = sRemoteServices.get(userId);
             if (remoteService == null) {
-                Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
-                PackageManager packageManager = context.getPackageManager();
-                intent.setPackage(packageManager.getPermissionControllerPackageName());
-                ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
-
                 remoteService = new RemoteService(context.getApplicationContext(),
-                        resolveInfo.getComponentInfo().getComponentName(), handler, userId);
+                        remoteServiceComponentName, handler, userId);
                 sRemoteServices.put(userId, remoteService);
             }
             mRemoteService = remoteService;
@@ -81,7 +102,16 @@
     }
 
     public RoleControllerManager(@NonNull Context context) {
-        this(context, context.getMainThreadHandler());
+        this(getRemoteServiceComponentName(context), context.getMainThreadHandler(), context);
+    }
+
+    @NonNull
+    private static ComponentName getRemoteServiceComponentName(@NonNull Context context) {
+        Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
+        PackageManager packageManager = context.getPackageManager();
+        intent.setPackage(packageManager.getPermissionControllerPackageName());
+        ResolveInfo resolveInfo = packageManager.resolveService(intent, 0);
+        return resolveInfo.getComponentInfo().getComponentName();
     }
 
     /**
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index db22f8d..cdf5d49 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -66,6 +66,7 @@
 
     @Override
     public void preExecute(ClientTransactionHandler client, IBinder token) {
+        client.countLaunchingActivities(1);
         client.updateProcessState(mProcState, false);
         client.updatePendingConfiguration(mCurConfig);
     }
@@ -82,6 +83,12 @@
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
+    @Override
+    public void postExecute(ClientTransactionHandler client, IBinder token,
+            PendingTransactionActions pendingActions) {
+        client.countLaunchingActivities(-1);
+    }
+
 
     // ObjectPoolItem implementation
 
diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java
index fa3d3b8d..941e9e2e 100644
--- a/core/java/android/attention/AttentionManagerInternal.java
+++ b/core/java/android/attention/AttentionManagerInternal.java
@@ -46,13 +46,6 @@
      */
     public abstract void cancelAttentionCheck(AttentionCallbackInternal callback);
 
-    /**
-     * Disables the dependants.
-     *
-     * Example: called if the service does not have sufficient permissions to perform the task.
-     */
-    public abstract void disableSelf();
-
     /** Internal interface for attention callback. */
     public abstract static class AttentionCallbackInternal {
         /**
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index f59bc98..8fb9501 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -24,7 +24,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
+import android.view.autofill.AutofillManager.AutofillClient;
 
 import java.io.PrintWriter;
 
@@ -73,10 +73,10 @@
     public boolean isAugmentedAutofillEnabled(@NonNull Context context) {
         if (!augmentedAutofillEnabled) return false;
 
-        final ContentCaptureClient contentCaptureClient = context.getContentCaptureClient();
-        if (contentCaptureClient == null) return false;
+        final AutofillClient autofillClient = context.getAutofillClient();
+        if (autofillClient == null) return false;
 
-        final ComponentName component = contentCaptureClient.contentCaptureClientGetComponentName();
+        final ComponentName component = autofillClient.autofillClientGetComponentName();
         return whitelistedActivitiesForAugmentedAutofill == null
                 || whitelistedActivitiesForAugmentedAutofill.contains(component);
     }
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index a41b5d3..c201e4d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -17,7 +17,6 @@
 package android.content;
 
 import android.annotation.UnsupportedAppUsage;
-import android.content.ContentProvider;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Parcel;
@@ -59,6 +58,7 @@
     private final ContentValues mValuesBackReferences;
     private final Map<Integer, Integer> mSelectionArgsBackReferences;
     private final boolean mYieldAllowed;
+    private final boolean mFailureAllowed;
 
     private final static String TAG = "ContentProviderOperation";
 
@@ -76,6 +76,7 @@
         mSelectionArgsBackReferences = builder.mSelectionArgsBackReferences;
         mValuesBackReferences = builder.mValuesBackReferences;
         mYieldAllowed = builder.mYieldAllowed;
+        mFailureAllowed = builder.mFailureAllowed;
     }
 
     private ContentProviderOperation(Parcel source) {
@@ -98,6 +99,7 @@
             }
         }
         mYieldAllowed = source.readInt() != 0;
+        mFailureAllowed = source.readInt() != 0;
     }
 
     /** @hide */
@@ -111,6 +113,7 @@
         mSelectionArgsBackReferences = cpo.mSelectionArgsBackReferences;
         mValuesBackReferences = cpo.mValuesBackReferences;
         mYieldAllowed = cpo.mYieldAllowed;
+        mFailureAllowed = cpo.mFailureAllowed;
     }
 
     public void writeToParcel(Parcel dest, int flags) {
@@ -157,6 +160,7 @@
             dest.writeInt(0);
         }
         dest.writeInt(mYieldAllowed ? 1 : 0);
+        dest.writeInt(mFailureAllowed ? 1 : 0);
     }
 
     /**
@@ -212,6 +216,11 @@
         return mYieldAllowed;
     }
 
+    /** {@hide} */
+    public boolean isFailureAllowed() {
+        return mFailureAllowed;
+    }
+
     /** @hide exposed for unit tests */
     @UnsupportedAppUsage
     public int getType() {
@@ -290,19 +299,35 @@
      */
     public ContentProviderResult apply(ContentProvider provider, ContentProviderResult[] backRefs,
             int numBackRefs) throws OperationApplicationException {
+        if (mFailureAllowed) {
+            try {
+                return applyInternal(provider, backRefs, numBackRefs);
+            } catch (Exception e) {
+                return new ContentProviderResult(e.getMessage());
+            }
+        } else {
+            return applyInternal(provider, backRefs, numBackRefs);
+        }
+    }
+
+    private ContentProviderResult applyInternal(ContentProvider provider,
+            ContentProviderResult[] backRefs, int numBackRefs)
+            throws OperationApplicationException {
         ContentValues values = resolveValueBackReferences(backRefs, numBackRefs);
         String[] selectionArgs =
                 resolveSelectionArgsBackReferences(backRefs, numBackRefs);
 
         if (mType == TYPE_INSERT) {
-            Uri newUri = provider.insert(mUri, values);
-            if (newUri == null) {
-                throw new OperationApplicationException("insert failed");
+            final Uri newUri = provider.insert(mUri, values);
+            if (newUri != null) {
+                return new ContentProviderResult(newUri);
+            } else {
+                throw new OperationApplicationException(
+                        "Insert into " + mUri + " returned no result");
             }
-            return new ContentProviderResult(newUri);
         }
 
-        int numRows;
+        final int numRows;
         if (mType == TYPE_DELETE) {
             numRows = provider.delete(mUri, mSelection, selectionArgs);
         } else if (mType == TYPE_UPDATE) {
@@ -328,7 +353,6 @@
                             final String expectedValue = values.getAsString(projection[i]);
                             if (!TextUtils.equals(cursorValue, expectedValue)) {
                                 // Throw exception when expected values don't match
-                                Log.e(TAG, this.toString());
                                 throw new OperationApplicationException("Found value " + cursorValue
                                         + " when expected " + expectedValue + " for column "
                                         + projection[i]);
@@ -340,13 +364,12 @@
                 cursor.close();
             }
         } else {
-            Log.e(TAG, this.toString());
             throw new IllegalStateException("bad type, " + mType);
         }
 
         if (mExpectedCount != null && mExpectedCount != numRows) {
-            Log.e(TAG, this.toString());
-            throw new OperationApplicationException("wrong number of rows: " + numRows);
+            throw new OperationApplicationException(
+                    "Expected " + mExpectedCount + " rows but actual " + numRows);
         }
 
         return new ContentProviderResult(numRows);
@@ -491,6 +514,7 @@
         private ContentValues mValuesBackReferences;
         private Map<Integer, Integer> mSelectionArgsBackReferences;
         private boolean mYieldAllowed;
+        private boolean mFailureAllowed;
 
         /** Create a {@link Builder} of a given type. The uri must not be null. */
         private Builder(int type, Uri uri) {
@@ -683,5 +707,11 @@
             mYieldAllowed = yieldAllowed;
             return this;
         }
+
+        /** {@hide} */
+        public Builder withFailureAllowed(boolean failureAllowed) {
+            mFailureAllowed = failureAllowed;
+            return this;
+        }
     }
 }
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index d90173c..b301011 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -16,10 +16,11 @@
 
 package android.content;
 
-import android.content.ContentProvider;
 import android.net.Uri;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
 
 /**
  * Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
@@ -28,26 +29,44 @@
 public class ContentProviderResult implements Parcelable {
     public final Uri uri;
     public final Integer count;
+    /** {@hide} */
+    public final String failure;
 
     public ContentProviderResult(Uri uri) {
-        if (uri == null) throw new IllegalArgumentException("uri must not be null");
-        this.uri = uri;
-        this.count = null;
+        this(Preconditions.checkNotNull(uri), null, null);
     }
 
     public ContentProviderResult(int count) {
+        this(null, count, null);
+    }
+
+    /** {@hide} */
+    public ContentProviderResult(String failure) {
+        this(null, null, failure);
+    }
+
+    /** {@hide} */
+    public ContentProviderResult(Uri uri, Integer count, String failure) {
+        this.uri = uri;
         this.count = count;
-        this.uri = null;
+        this.failure = failure;
     }
 
     public ContentProviderResult(Parcel source) {
-        int type = source.readInt();
-        if (type == 1) {
-            count = source.readInt();
+        if (source.readInt() != 0) {
+            uri = Uri.CREATOR.createFromParcel(source);
+        } else {
             uri = null;
+        }
+        if (source.readInt() != 0) {
+            count = source.readInt();
         } else {
             count = null;
-            uri = Uri.CREATOR.createFromParcel(source);
+        }
+        if (source.readInt() != 0) {
+            failure = source.readString();
+        } else {
+            failure = null;
         }
     }
 
@@ -55,37 +74,63 @@
     public ContentProviderResult(ContentProviderResult cpr, int userId) {
         uri = ContentProvider.maybeAddUserId(cpr.uri, userId);
         count = cpr.count;
+        failure = cpr.failure;
     }
 
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
-        if (uri == null) {
+        if (uri != null) {
+            dest.writeInt(1);
+            uri.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        if (count != null) {
             dest.writeInt(1);
             dest.writeInt(count);
         } else {
-            dest.writeInt(2);
-            uri.writeToParcel(dest, 0);
+            dest.writeInt(0);
+        }
+        if (failure != null) {
+            dest.writeInt(1);
+            dest.writeString(failure);
+        } else {
+            dest.writeInt(0);
         }
     }
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
     public static final @android.annotation.NonNull Creator<ContentProviderResult> CREATOR =
             new Creator<ContentProviderResult>() {
+        @Override
         public ContentProviderResult createFromParcel(Parcel source) {
             return new ContentProviderResult(source);
         }
 
+        @Override
         public ContentProviderResult[] newArray(int size) {
             return new ContentProviderResult[size];
         }
     };
 
+    @Override
     public String toString() {
+        final StringBuilder sb = new StringBuilder("ContentProviderResult(");
         if (uri != null) {
-            return "ContentProviderResult(uri=" + uri.toString() + ")";
+            sb.append("uri=" + uri + " ");
         }
-        return "ContentProviderResult(count=" + count + ")";
+        if (count != null) {
+            sb.append("count=" + count + " ");
+        }
+        if (uri != null) {
+            sb.append("failure=" + failure + " ");
+        }
+        sb.deleteCharAt(sb.length() - 1);
+        sb.append(")");
+        return sb.toString();
     }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5a844aa..0ba457e 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -70,7 +70,6 @@
 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;
@@ -5414,14 +5413,6 @@
     /**
      * @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/inputmethodservice/MultiClientInputMethodServiceDelegate.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
index 0604f6a6..4b02085 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
@@ -374,4 +374,15 @@
     public boolean isUidAllowedOnDisplay(int displayId, int uid) {
         return mImpl.isUidAllowedOnDisplay(displayId, uid);
     }
+
+    /**
+     * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
+     * respectively.
+     *
+     * @param clientId client ID to activate/deactivate.
+     * @param active {@code true} to activate a client.
+     */
+    public void setActive(int clientId, boolean active) {
+        mImpl.setActive(clientId, active);
+    }
 }
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
index bbe3a7f..04db8d6 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
@@ -190,4 +190,8 @@
     boolean isUidAllowedOnDisplay(int displayId, int uid) {
         return mPrivOps.isUidAllowedOnDisplay(displayId, uid);
     }
+
+    void setActive(int clientId, boolean active) {
+        mPrivOps.setActive(clientId, active);
+    }
 }
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index b6c4fe2..68826cb 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -197,7 +197,7 @@
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkSend((network != null
-                ? network.netId : NETID_UNSET), query, query.length, flags);
+                ? network.getNetIdForResolv() : NETID_UNSET), query, query.length, flags);
         } catch (ErrnoException e) {
             executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
             return;
@@ -238,7 +238,7 @@
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkQuery((network != null
-                    ? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
+                    ? network.getNetIdForResolv() : NETID_UNSET), domain, nsClass, nsType, flags);
         } catch (ErrnoException e) {
             executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
             return;
@@ -346,7 +346,8 @@
         if (queryIpv6) {
             try {
                 v6fd = resNetworkQuery((network != null
-                        ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
+                        ? network.getNetIdForResolv() : NETID_UNSET),
+                        domain, CLASS_IN, TYPE_AAAA, flags);
             } catch (ErrnoException e) {
                 executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
                 return;
@@ -365,7 +366,8 @@
         if (queryIpv4) {
             try {
                 v4fd = resNetworkQuery((network != null
-                        ? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
+                        ? network.getNetIdForResolv() : NETID_UNSET),
+                        domain, CLASS_IN, TYPE_A, flags);
             } catch (ErrnoException e) {
                 if (queryIpv6) resNetworkCancel(v6fd);  // Closes fd, marks it invalid.
                 executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
@@ -423,7 +425,7 @@
         final FileDescriptor queryfd;
         try {
             queryfd = resNetworkQuery((network != null
-                    ? network.netId : NETID_UNSET), domain, CLASS_IN, nsType, flags);
+                    ? network.getNetIdForResolv() : NETID_UNSET), domain, CLASS_IN, nsType, flags);
         } catch (ErrnoException e) {
             executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
             return;
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index b8d7cf1..a55d9d0 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -20,6 +20,8 @@
 import android.os.SystemClock;
 import android.util.Log;
 
+import com.android.internal.util.TrafficStatsConstants;
+
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
@@ -99,7 +101,8 @@
 
     public boolean requestTime(InetAddress address, int port, int timeout, Network network) {
         DatagramSocket socket = null;
-        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                TrafficStatsConstants.TAG_SYSTEM_NTP);
         try {
             socket = new DatagramSocket();
             network.bindSocket(socket);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 49c6f74..4332d8a 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -90,6 +90,42 @@
     public static final int UID_TETHERING = -5;
 
     /**
+     * Tag values in this range are reserved for the network stack. The network stack is
+     * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline
+     * module separate process, and as the system UID otherwise.
+     */
+    /** @hide */
+    @SystemApi
+    public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00;
+    /** @hide */
+    @SystemApi
+    public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF;
+
+    /**
+     * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services
+     * like DownloadManager when performing traffic on behalf of an application.
+     */
+    // Please note there is no enforcement of these constants, so do not rely on them to
+    // determine that the caller is a system caller.
+    /** @hide */
+    @SystemApi
+    public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00;
+    /** @hide */
+    @SystemApi
+    public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F;
+
+    /**
+     * Tag values between these ranges are reserved for the network stack to do traffic
+     * on behalf of applications. It is a subrange of the range above.
+     */
+    /** @hide */
+    @SystemApi
+    public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80;
+    /** @hide */
+    @SystemApi
+    public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F;
+
+    /**
      * Default tag value for {@link DownloadManager} traffic.
      *
      * @hide
@@ -127,26 +163,9 @@
      */
     public static final int TAG_SYSTEM_APP = 0xFFFFFF05;
 
+    // TODO : remove this constant when Wifi code is updated
     /** @hide */
-    @SystemApi
-    @TestApi
-    public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40;
-    /** @hide */
-    public static final int TAG_SYSTEM_NTP = 0xFFFFFF41;
-    /** @hide */
-    @SystemApi
-    @TestApi
     public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42;
-    /** @hide */
-    public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43;
-    /** @hide */
-    public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
-    /** @hide */
-    public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
-    /** @hide */
-    @SystemApi
-    @TestApi
-    public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46;
 
     private static INetworkStatsService sStatsService;
 
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 166de3f..6c498c7 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -493,6 +493,7 @@
      * @param onPropertyChangedListener The listener to add.
      * @hide
      * @see #removeOnPropertyChangedListener(OnPropertyChangedListener)
+     * @removed
      */
     @SystemApi
     @TestApi
@@ -569,6 +570,7 @@
      * @param onPropertyChangedListener The listener to remove.
      * @hide
      * @see #addOnPropertyChangedListener(String, Executor, OnPropertyChangedListener)
+     * @removed
      */
     @SystemApi
     @TestApi
@@ -737,6 +739,7 @@
      * Override {@link #onPropertyChanged(String, String, String)} to handle callbacks for changes.
      *
      * @hide
+     * @removed
      */
     @SystemApi
     @TestApi
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0491c73..488f417 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -955,18 +955,16 @@
             "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
 
     /**
-     * Activity Action: Open the advanced power usage details page of an associated app.
+     * Activity Action: Open the battery details page of an associated app.
      * <p>
      * Input: Intent's data URI set with an application name, using the
      * "package" schema (like "package:com.my.app")
      * <p>
      * Output: Nothing.
-     *
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL =
-            "android.settings.VIEW_ADVANCED_POWER_USAGE_DETAIL";
+    public static final String ACTION_APP_BATTERY_SETTINGS =
+            "android.settings.APP_BATTERY_SETTINGS";
 
     /**
      * Activity Action: Show screen for controlling background data
@@ -1533,6 +1531,9 @@
     /**
      * Activity Action: Show More default apps settings.
      * <p>
+     * If a Settings activity handles this intent action, a "More defaults" entry will be shown in
+     * the Default apps settings, and clicking it will launch that activity.
+     * <p>
      * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
      * <p>
      * Input: Nothing.
@@ -5801,6 +5802,14 @@
                 "autofill_field_classification";
 
         /**
+         * Boolean indicating if the dark mode dialog shown on first toggle has been seen.
+         *
+         * @hide
+         */
+        public static final String DARK_MODE_DIALOG_SEEN =
+                "dark_mode_dialog_seen";
+
+        /**
          * Defines value returned by {@link android.service.autofill.UserData#getMaxUserDataSize()}.
          *
          * @hide
@@ -8139,7 +8148,14 @@
         public static final String FACE_UNLOCK_ATTENTION_REQUIRED =
                 "face_unlock_attention_required";
 
-        private static final Validator FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR = BOOLEAN_VALIDATOR;
+        /**
+         * Whether or not face unlock requires a diverse set of poses during enrollment. This is a
+         * cached value, the source of truth is obtained through the HAL.
+         * @hide
+         */
+        public static final String FACE_UNLOCK_DIVERSITY_REQUIRED =
+                "face_unlock_diversity_required";
+
 
         /**
          * Whether or not face unlock is allowed for apps (through BiometricPrompt).
@@ -8797,7 +8813,6 @@
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             FACE_UNLOCK_KEYGUARD_ENABLED,
             FACE_UNLOCK_DISMISSES_KEYGUARD,
-            FACE_UNLOCK_ATTENTION_REQUIRED,
             FACE_UNLOCK_APP_ENABLED,
             FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
             ASSIST_GESTURE_ENABLED,
@@ -8842,6 +8857,7 @@
             SILENCE_NOTIFICATION_GESTURE_COUNT,
             SILENCE_CALL_GESTURE_COUNT,
             SILENCE_TIMER_GESTURE_COUNT,
+            DARK_MODE_DIALOG_SEEN
         };
 
         /**
@@ -8964,8 +8980,6 @@
             VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
                     FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
-            VALIDATORS.put(FACE_UNLOCK_ATTENTION_REQUIRED,
-                    FACE_UNLOCK_ATTENTION_REQUIRED_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
                     FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
@@ -9024,6 +9038,7 @@
             VALIDATORS.put(SILENCE_CALL_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(SILENCE_NOTIFICATION_GESTURE_COUNT, SILENCE_GESTURE_COUNT_VALIDATOR);
             VALIDATORS.put(ODI_CAPTIONS_ENABLED, ODI_CAPTIONS_ENABLED_VALIDATOR);
+            VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
         }
 
         /**
diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java
index 6172ce5..49ab5db 100644
--- a/core/java/android/service/attention/AttentionService.java
+++ b/core/java/android/service/attention/AttentionService.java
@@ -21,13 +21,11 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.Service;
-import android.attention.AttentionManagerInternal;
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
 
 import com.android.internal.util.Preconditions;
-import com.android.server.LocalServices;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -132,19 +130,6 @@
     }
 
     /**
-     * Disables the dependants.
-     *
-     * Example: called if the service does not have sufficient permissions to perform the task.
-     */
-    public final void disableSelf() {
-        AttentionManagerInternal attentionManager = LocalServices.getService(
-                AttentionManagerInternal.class);
-        if (attentionManager != null) {
-            attentionManager.disableSelf();
-        }
-    }
-
-    /**
      * Checks the user attention and calls into the provided callback.
      *
      * @param callback the callback to return the result to
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 5be73b9..02ce873 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -46,9 +46,9 @@
 import android.view.contentcapture.ContentCaptureManager;
 import android.view.contentcapture.ContentCaptureSession;
 import android.view.contentcapture.ContentCaptureSessionId;
+import android.view.contentcapture.DataRemovalRequest;
 import android.view.contentcapture.IContentCaptureDirectManager;
 import android.view.contentcapture.MainContentCaptureSession;
-import android.view.contentcapture.UserDataRemovalRequest;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -86,11 +86,28 @@
      * <code>&lt;{@link
      * android.R.styleable#ContentCaptureService content-capture-service}&gt;</code> tag.
      *
-     * <p>This is a a sample XML file configuring a ContentCaptureService:
-     * <pre> &lt;content-capture-service
-     *     android:settingsActivity="foo.bar.SettingsActivity"
-     *     . . .
-     * /&gt;</pre>
+     * <p>Here's an example of how to use it on {@code AndroidManifest.xml}:
+     *
+     * <pre>
+     * &lt;service android:name=".MyContentCaptureService"
+     *     android:permission="android.permission.BIND_CONTENT_CAPTURE_SERVICE"&gt;
+     *   &lt;intent-filter&gt;
+     *     &lt;action android:name="android.service.contentcapture.ContentCaptureService" /&gt;
+     *   &lt;/intent-filter&gt;
+     *
+     *   &lt;meta-data
+     *       android:name="android.content_capture"
+     *       android:resource="@xml/my_content_capture_service"/&gt;
+     * &lt;/service&gt;
+     * </pre>
+     *
+     * <p>And then on {@code res/xml/my_content_capture_service.xml}:
+     *
+     * <pre>
+     *   &lt;content-capture-service xmlns:android="http://schemas.android.com/apk/res/android"
+     *       android:settingsActivity="my.package.MySettingsActivity"&gt;
+     *   &lt;/content-capture-service&gt;
+     * </pre>
      */
     public static final String SERVICE_META_DATA = "android.content_capture";
 
@@ -138,7 +155,7 @@
         }
 
         @Override
-        public void onUserDataRemovalRequest(UserDataRemovalRequest request) {
+        public void onDataRemovalRequest(DataRemovalRequest request) {
             mHandler.sendMessage(
                     obtainMessage(ContentCaptureService::handleOnUserDataRemovalRequest,
                             ContentCaptureService.this, request));
@@ -288,12 +305,12 @@
     }
 
     /**
-     * Notifies the service that the app requested to remove data associated with the user.
+     * Notifies the service that the app requested to remove content capture data.
      *
-     * @param request the user data requested to be removed
+     * @param request the content capture data requested to be removed
      */
-    public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
-        if (sVerbose) Log.v(TAG, "onUserDataRemovalRequest()");
+    public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+        if (sVerbose) Log.v(TAG, "onDataRemovalRequest()");
     }
 
     /**
@@ -449,8 +466,8 @@
         onDestroyContentCaptureSession(new ContentCaptureSessionId(sessionId));
     }
 
-    private void handleOnUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
-        onUserDataRemovalRequest(request);
+    private void handleOnUserDataRemovalRequest(@NonNull DataRemovalRequest request) {
+        onDataRemovalRequest(request);
     }
 
     private void handleOnActivityEvent(@NonNull ActivityEvent event) {
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index 03e1b78..a7578af9 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -21,7 +21,7 @@
 import android.service.contentcapture.ActivityEvent;
 import android.service.contentcapture.SnapshotData;
 import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -39,6 +39,6 @@
                           in IResultReceiver clientReceiver, int initialState);
     void onSessionFinished(int sessionId);
     void onActivitySnapshot(int sessionId, in SnapshotData snapshotData);
-    void onUserDataRemovalRequest(in UserDataRemovalRequest request);
+    void onDataRemovalRequest(in DataRemovalRequest request);
     void onActivityEvent(in ActivityEvent event);
 }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index e3e63e5..0de17ca 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -17,7 +17,6 @@
 package android.service.voice;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.UnsupportedAppUsage;
 import android.app.Service;
@@ -41,6 +40,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -211,11 +211,11 @@
      *
      * @param voiceActions A set of checked voice actions.
      * @return Returns a subset of checked voice actions. Additional voice actions in the
-     * returned set will be ignored. Returns null or empty set if no actions are supported.
+     * returned set will be ignored. Returns empty set if no actions are supported.
      */
-    @Nullable
+    @NonNull
     public Set<String> onGetSupportedVoiceActions(@NonNull Set<String> voiceActions) {
-        return null;
+        return Collections.emptySet();
     }
 
     @Override
@@ -272,7 +272,7 @@
             try {
                 Set<String> voiceActionsSet = new ArraySet<>(voiceActions);
                 Set<String> resultSet = onGetSupportedVoiceActions(voiceActionsSet);
-                callback.onComplete(resultSet == null ? null : new ArrayList<>(resultSet));
+                callback.onComplete(new ArrayList<>(resultSet));
             } catch (RemoteException e) {
             }
         }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 6f27447..5b5f3b8 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -123,7 +123,7 @@
 
     /**
      * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
-     * from an Android automotive system Ui.
+     * from an Android automotive system UI.
      */
     public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7;
 
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index f2747cf..1bcfc05 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -34,11 +34,32 @@
     public static final int DENSITY_LOW = 120;
 
     /**
+     * Intermediate density for screens that sit between {@link #DENSITY_LOW} (120dpi) and
+     * {@link #DENSITY_MEDIUM} (160dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_MEDIUM} assets for them.
+     */
+    public static final int DENSITY_140 = 140;
+
+    /**
      * Standard quantized DPI for medium-density screens.
      */
     public static final int DENSITY_MEDIUM = 160;
 
     /**
+     * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+     * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+     */
+    public static final int DENSITY_180 = 180;
+
+    /**
+     * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+     * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+     */
+    public static final int DENSITY_200 = 200;
+
+    /**
      * This is a secondary density, added for some common screen configurations.
      * It is recommended that applications not generally target this as a first
      * class density -- that is, don't supply specific graphics for this
@@ -58,6 +79,13 @@
     public static final int DENSITY_TV = 213;
 
     /**
+     * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
+     * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
+     */
+    public static final int DENSITY_220 = 220;
+
+    /**
      * Standard quantized DPI for high-density screens.
      */
     public static final int DENSITY_HIGH = 240;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index feff9db..f2aaead 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -63,7 +63,6 @@
         DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
         DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
         DEFAULT_FLAGS.put(PIXEL_WALLPAPER_CATEGORY_SWITCH, "false");
-        DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "true");
         DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
     }
 
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index 8eccc04..6fcdd71 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -20,6 +20,8 @@
 import android.annotation.Nullable;
 import android.graphics.Rect;
 
+import com.android.internal.util.Preconditions;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -31,6 +33,8 @@
  */
 class GestureExclusionTracker {
     private boolean mGestureExclusionViewsChanged = false;
+    private boolean mRootGestureExclusionRectsChanged = false;
+    private List<Rect> mRootGestureExclusionRects = Collections.emptyList();
     private List<GestureExclusionViewInfo> mGestureExclusionViewInfos = new ArrayList<>();
     private List<Rect> mGestureExclusionRects = Collections.emptyList();
 
@@ -59,9 +63,9 @@
 
     @Nullable
     public List<Rect> computeChangedRects() {
-        boolean changed = false;
+        boolean changed = mRootGestureExclusionRectsChanged;
         final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator();
-        final List<Rect> rects = new ArrayList<>();
+        final List<Rect> rects = new ArrayList<>(mRootGestureExclusionRects);
         while (i.hasNext()) {
             final GestureExclusionViewInfo info = i.next();
             switch (info.update()) {
@@ -79,6 +83,7 @@
         }
         if (changed || mGestureExclusionViewsChanged) {
             mGestureExclusionViewsChanged = false;
+            mRootGestureExclusionRectsChanged = false;
             if (!mGestureExclusionRects.equals(rects)) {
                 mGestureExclusionRects = rects;
                 return rects;
@@ -87,6 +92,17 @@
         return null;
     }
 
+    public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+        Preconditions.checkNotNull(rects, "rects must not be null");
+        mRootGestureExclusionRects = rects;
+        mRootGestureExclusionRectsChanged = true;
+    }
+
+    @NonNull
+    public List<Rect> getRootSystemGestureExclusionRects() {
+        return mRootGestureExclusionRects;
+    }
+
     private static class GestureExclusionViewInfo {
         public static final int CHANGED = 0;
         public static final int UNCHANGED = 1;
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 2ba1e01..d415387 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -85,6 +85,7 @@
     @Override
     public void onWindowFocusLost() {
         mHasWindowFocus = false;
+        getImm().unregisterImeConsumer(this);
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 51bcbbd..096c988 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1377,59 +1377,6 @@
      */
     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
 
-    /** @hide */
-    @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
-            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
-            IMPORTANT_FOR_CONTENT_CAPTURE_YES,
-            IMPORTANT_FOR_CONTENT_CAPTURE_NO,
-            IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
-            IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ContentCaptureImportance {}
-
-    /**
-     * Automatically determine whether a view is important for content capture.
-     *
-     * @see #isImportantForContentCapture()
-     * @see #setImportantForContentCapture(int)
-     */
-    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
-
-    /**
-     * The view is important for content capture, and its children (if any) will be traversed.
-     *
-     * @see #isImportantForContentCapture()
-     * @see #setImportantForContentCapture(int)
-     */
-    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
-
-    /**
-     * The view is not important for content capture, but its children (if any) will be traversed.
-     *
-     * @see #isImportantForContentCapture()
-     * @see #setImportantForContentCapture(int)
-     */
-    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
-
-    /**
-     * The view is important for content capture, but its children (if any) will not be traversed.
-     *
-     * @see #isImportantForContentCapture()
-     * @see #setImportantForContentCapture(int)
-     */
-    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
-
-    /**
-     * The view is not important for content capture, and its children (if any) will not be
-     * traversed.
-     *
-     * @see #isImportantForContentCapture()
-     * @see #setImportantForContentCapture(int)
-     */
-    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
-
-
     /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
@@ -3402,55 +3349,6 @@
 
     /* End of masks for mPrivateFlags3 */
 
-    /*
-     * Masks for mPrivateFlags4, as generated by dumpFlags():
-     *
-     * |-------|-------|-------|-------|
-     *                             1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
-     *                            1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED
-     *                           1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED
-     *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
-     *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
-     *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
-     * |-------|-------|-------|-------|
-     */
-
-    /**
-     * Mask for obtaining the bits which specify how to determine
-     * whether a view is important for autofill.
-     *
-     * <p>NOTE: the important for content capture values were the first flags added and are set in
-     * the rightmost position, so we don't need to shift them
-     */
-    private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
-            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
-            | IMPORTANT_FOR_CONTENT_CAPTURE_NO
-            | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
-            | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
-
-    /*
-     * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
-     * should be called.
-     *
-     * The idea is to call notifyAppeared() after the view is layout and visible, then call
-     * notifyDisappeared() when it's gone (without known when it was removed from the parent).
-     */
-    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10;
-    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20;
-
-    /*
-     * Flags used to cache the value returned by isImportantForContentCapture while the view
-     * hierarchy is being traversed.
-     */
-    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED = 0x40;
-    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE = 0x80;
-
-    private static final int PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK =
-            PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
-            | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
-
-    /* End of masks for mPrivateFlags4 */
-
     /** @hide */
     protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
     /** @hide */
@@ -4074,8 +3972,6 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 129147060)
     int mPrivateFlags3;
 
-    private int mPrivateFlags4;
-
     /**
      * This view's request for the visibility of the status bar.
      * @hide
@@ -5808,11 +5704,6 @@
                         setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
                     }
                     break;
-                case R.styleable.View_importantForContentCapture:
-                    if (a.peekValue(attr) != null) {
-                        setImportantForContentCapture(a.getInt(attr,
-                                IMPORTANT_FOR_CONTENT_CAPTURE_AUTO));
-                    }
                 case R.styleable.View_defaultFocusHighlightEnabled:
                     if (a.peekValue(attr) != null) {
                         setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
@@ -8532,62 +8423,6 @@
         onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
     }
 
-    /**
-     * Populates a {@link ViewStructure} for content capture.
-     *
-     * <p>This method is called after a view is that is eligible for content capture
-     * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
-     * the user, and the activity rendering the view is enabled for content capture) is laid out and
-     * is visible.
-     *
-     * <p>The populated structure is then passed to the service through
-     * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
-     *
-     * <p><b>Note: </b>views that manage a virtual structure under this view must populate just
-     * the node representing this view and return right away, then asynchronously report (not
-     * necessarily in the UI thread) when the children nodes appear, disappear or have their text
-     * changed by calling
-     * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
-     * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
-     * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)}
-     * respectively. The structure for the a child must be created using
-     * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
-     * {@code autofillId} for a child can be obtained either through
-     * {@code childStructure.getAutofillId()} or
-     * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
-     *
-     * <p>When the virtual view hierarchy represents a web page, you should also:
-     *
-     * <ul>
-     *   <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content
-     *   capture events should be generate for that URL.
-     *   <li>Create a new {@link ContentCaptureSession} child for every HTML element that
-     *   renders a new URL (like an {@code IFRAME}) and use that session to notify events from
-     *   that subtree.
-     * </ul>
-     *
-     * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
-     * <ul>
-     *   <li>{@link ViewStructure#setChildCount(int)}
-     *   <li>{@link ViewStructure#addChildCount(int)}
-     *   <li>{@link ViewStructure#getChildCount()}
-     *   <li>{@link ViewStructure#newChild(int)}
-     *   <li>{@link ViewStructure#asyncNewChild(int)}
-     *   <li>{@link ViewStructure#asyncCommit()}
-     *   <li>{@link ViewStructure#setWebDomain(String)}
-     *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
-     *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
-     *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
-     *   <li>{@link ViewStructure#setAlpha(float)}
-     *   <li>{@link ViewStructure#setElevation(float)}
-     *   <li>{@link ViewStructure#setTransformation(Matrix)}
-     *
-     * </ul>
-     */
-    public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
-        onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
-    }
-
     /** @hide */
     protected void onProvideStructure(@NonNull ViewStructure structure,
             @ViewStructureType int viewFor, int flags) {
@@ -9225,265 +9060,6 @@
     }
 
     /**
-     * Gets the mode for determining whether this view is important for content capture.
-     *
-     * <p>See {@link #setImportantForContentCapture(int)} and
-     * {@link #isImportantForContentCapture()} for more info about this mode.
-     *
-     * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
-     * {@link #setImportantForContentCapture(int)}.
-     *
-     * @attr ref android.R.styleable#View_importantForContentCapture
-     */
-    @ViewDebug.ExportedProperty(mapping = {
-            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
-            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
-            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
-            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
-                to = "yesExcludeDescendants"),
-            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
-                to = "noExcludeDescendants")})
-    @InspectableProperty(enumMapping = {
-            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, name = "auto"),
-            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES, name = "yes"),
-            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO, name = "no"),
-            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
-                    name = "yesExcludeDescendants"),
-            @EnumEntry(value = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
-                    name = "noExcludeDescendants"),
-    })
-    public @ContentCaptureImportance int getImportantForContentCapture() {
-        // NOTE: the important for content capture values were the first flags added and are set in
-        // the rightmost position, so we don't need to shift them
-        return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
-    }
-
-    /**
-     * Sets the mode for determining whether this view is considered important for content capture.
-     *
-     * <p>The platform determines the importance for autofill automatically but you
-     * can use this method to customize the behavior. Typically, a view that provides text should
-     * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
-     *
-     * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
-     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
-     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
-     * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
-     *
-     * @attr ref android.R.styleable#View_importantForContentCapture
-     */
-    public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
-        // Reset first
-        mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
-        // Then set again
-        // NOTE: the important for content capture values were the first flags added and are set in
-        // the rightmost position, so we don't need to shift them
-        mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
-    }
-
-    /**
-     * Hints the Android System whether this view is considered important for content capture, based
-     * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
-     * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
-     *
-     * <p>See {@link ContentCaptureManager} for more info about content capture.
-     *
-     * @return whether the view is considered important for content capture.
-     *
-     * @see #setImportantForContentCapture(int)
-     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
-     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
-     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
-     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
-     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
-     */
-    public final boolean isImportantForContentCapture() {
-        boolean isImportant;
-        if ((mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED) != 0) {
-            isImportant = (mPrivateFlags4 & PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE) != 0;
-            return isImportant;
-        }
-
-        isImportant = calculateIsImportantForContentCapture();
-
-        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
-        if (isImportant) {
-            mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
-        }
-        mPrivateFlags4 |= PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED;
-        return isImportant;
-    }
-
-    /**
-     * Calculates whether the flag is important for content capture so it can be used by
-     * {@link #isImportantForContentCapture()} while the tree is traversed.
-     */
-    private boolean calculateIsImportantForContentCapture() {
-        // Check parent mode to ensure we're important
-        ViewParent parent = mParent;
-        while (parent instanceof View) {
-            final int parentImportance = ((View) parent).getImportantForContentCapture();
-            if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
-                    || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
-                if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
-                    Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
-                            + "content capture because parent " + parent + "'s importance is "
-                            + parentImportance);
-                }
-                return false;
-            }
-            parent = parent.getParent();
-        }
-
-        final int importance = getImportantForContentCapture();
-
-        // First, check the explicit states.
-        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
-                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
-            return true;
-        }
-        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
-                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
-            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
-                Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
-                        + "capture because its importance is " + importance);
-            }
-            return false;
-        }
-
-        // Then use some heuristics to handle AUTO.
-        if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
-            Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
-                    + " on view " + this);
-            return false;
-        }
-
-        // View group is important if at least one children also is
-        if (this instanceof ViewGroup) {
-            final ViewGroup group = (ViewGroup) this;
-            for (int i = 0; i < group.getChildCount(); i++) {
-                final View child = group.getChildAt(i);
-                if (child.isImportantForContentCapture()) {
-                    return true;
-                }
-            }
-        }
-
-        // If the app developer explicitly set hints or autofill hintsfor it, it's important.
-        if (getAutofillHints() != null) {
-            return true;
-        }
-
-        // Otherwise, assume it's not important...
-        return false;
-    }
-
-    /**
-     * Helper used to notify the {@link ContentCaptureManager} when the view is removed or
-     * added, based on whether it's laid out and visible, and without knowing if the parent removed
-     * it from the view hierarchy.
-     *
-     * <p>This method is called from many places (visibility changed, view laid out, view attached
-     * or detached to/from window, etc...) and hence must contain the logic to call the manager, as
-     * described below:
-     *
-     * <ol>
-     *   <li>It should only be called when content capture is enabled for the view.
-     *   <li>It must call viewAppeared() before viewDisappeared()
-     *   <li>viewAppearead() can only be called when the view is visible and laidout
-     *   <li>It should not call the same event twice.
-     * </ol>
-     */
-    private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
-        AttachInfo ai = mAttachInfo;
-        // Skip it while the view is being laided out for the first time
-        if (ai != null && !ai.mReadyForContentCaptureUpdates) return;
-
-        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
-            Trace.traceBegin(Trace.TRACE_TAG_VIEW,
-                    "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
-        }
-        try {
-            notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-    }
-
-    private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
-        AttachInfo ai = mAttachInfo;
-
-        // First check if context has client, so it saves a service lookup when it doesn't
-        if (mContext.getContentCaptureOptions() == null) return;
-
-        // Then check if it's enabled in the context...
-        final ContentCaptureManager ccm = ai != null ? ai.getContentCaptureManager(mContext)
-                : mContext.getSystemService(ContentCaptureManager.class);
-        if (ccm == null || !ccm.isContentCaptureEnabled()) return;
-
-        // ... and finally at the view level
-        // NOTE: isImportantForContentCapture() is more expensive than cm.isContentCaptureEnabled()
-        if (!isImportantForContentCapture()) return;
-
-        ContentCaptureSession session = getContentCaptureSession();
-        if (session == null) return;
-
-        if (appeared) {
-            if (!isLaidOut() || getVisibility() != VISIBLE
-                    || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) {
-                if (DEBUG_CONTENT_CAPTURE) {
-                    Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid="
-                            + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
-                            + ", visible=" + (getVisibility() == VISIBLE)
-                            + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
-                                    & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
-                            + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
-                                    & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
-                }
-                return;
-            }
-            setNotifiedContentCaptureAppeared();
-
-            if (ai != null) {
-                ai.delayNotifyContentCaptureEvent(session, this, appeared);
-            } else {
-                if (DEBUG_CONTENT_CAPTURE) {
-                    Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
-                }
-            }
-        } else {
-            if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
-                    || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
-                if (DEBUG_CONTENT_CAPTURE) {
-                    Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + ": laid="
-                            + isLaidOut() + ", visibleToUser=" + isVisibleToUser()
-                            + ", visible=" + (getVisibility() == VISIBLE)
-                            + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4
-                                    & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)
-                            + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4
-                                    & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0));
-                }
-                return;
-            }
-            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
-            mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
-
-            if (ai != null) {
-                ai.delayNotifyContentCaptureEvent(session, this, appeared);
-            } else {
-                if (DEBUG_CONTENT_CAPTURE) {
-                    Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
-                }
-            }
-        }
-    }
-
-    private void setNotifiedContentCaptureAppeared() {
-        mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
-        mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED;
-    }
-
-    /**
      * Sets the (optional) {@link ContentCaptureSession} associated with this view.
      *
      * <p>This method should be called when you need to associate a {@link ContentCaptureContext} to
@@ -9739,68 +9315,6 @@
     }
 
     /**
-     * Dispatches the initial content capture events for a view structure.
-     *
-     * @hide
-     */
-    public void dispatchInitialProvideContentCaptureStructure() {
-        AttachInfo ai = mAttachInfo;
-        if (ai == null) {
-            Log.w(CONTENT_CAPTURE_LOG_TAG,
-                    "dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
-            return;
-        }
-        ContentCaptureManager ccm = ai.mContentCaptureManager;
-        if (ccm == null) {
-            Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
-                    + "no ContentCaptureManager for " + this);
-            return;
-        }
-
-        // We must set it before checkign if the view itself is important, because it might
-        // initially not be (for example, if it's empty), although that might change later (for
-        // example, if important views are added)
-        ai.mReadyForContentCaptureUpdates = true;
-
-        if (!isImportantForContentCapture()) {
-            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
-                Log.d(CONTENT_CAPTURE_LOG_TAG,
-                        "dispatchProvideContentCaptureStructure(): decorView is not important");
-            }
-            return;
-        }
-
-        ai.mContentCaptureManager = ccm;
-
-        ContentCaptureSession session = getContentCaptureSession();
-        if (session == null) {
-            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.DEBUG)) {
-                Log.d(CONTENT_CAPTURE_LOG_TAG,
-                        "dispatchProvideContentCaptureStructure(): no session for " + this);
-            }
-            return;
-        }
-
-        session.internalNotifyViewTreeEvent(/* started= */ true);
-        try {
-            dispatchProvideContentCaptureStructure();
-        } finally {
-            session.internalNotifyViewTreeEvent(/* started= */ false);
-        }
-    }
-
-    /** @hide */
-    void dispatchProvideContentCaptureStructure() {
-        ContentCaptureSession session = getContentCaptureSession();
-        if (session != null) {
-            ViewStructure structure = session.newViewStructure(this);
-            onProvideContentCaptureStructure(structure, /* flags= */ 0);
-            setNotifiedContentCaptureAppeared();
-            session.notifyViewAppeared(structure);
-        }
-    }
-
-    /**
      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
      *
      * Note: Called from the default {@link AccessibilityDelegate}.
@@ -12134,14 +11648,11 @@
     }
 
     /**
-     * When screen readers (one type of accessibility tool) decide what should be read to the
-     * user, they typically look for input focusable ({@link #isFocusable()}) parents of
-     * non-focusable text items, and read those focusable parents and their non-focusable children
-     * as a unit. In some situations, this behavior is desirable for views that should not take
-     * input focus. Setting an item to be screen reader focusable requests that the view be
-     * treated as a unit by screen readers without any effect on input focusability. The default
-     * value of {@code false} lets screen readers use other signals, like focusable, to determine
-     * how to group items.
+     * Sets whether this View should be a focusable element for screen readers
+     * and include non-focusable Views from its subtree when providing feedback.
+     * <p>
+     * Note: this is similar to using <a href="#attr_android:focusable">{@code android:focusable},
+     * but does not impact input focus behavior.
      *
      * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader
      *                              accessibility tools.
@@ -13753,7 +13264,6 @@
     public void dispatchStartTemporaryDetach() {
         mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
         notifyEnterOrExitForAutoFillIfNeeded(false);
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
         onStartTemporaryDetach();
     }
 
@@ -13780,7 +13290,6 @@
             notifyFocusChangeToInputMethodManager(true /* hasFocus */);
         }
         notifyEnterOrExitForAutoFillIfNeeded(true);
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
     }
 
     /**
@@ -14372,8 +13881,6 @@
                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
             }
         }
-
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
     }
 
     /**
@@ -18069,7 +17576,6 @@
         }
 
         // Reset content capture caches
-        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
         mCachedContentCaptureSession = null;
 
         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
@@ -20079,7 +19585,6 @@
         needGlobalAttributesUpdate(false);
 
         notifyEnterOrExitForAutoFillIfNeeded(true);
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -20129,7 +19634,6 @@
         }
 
         notifyEnterOrExitForAutoFillIfNeeded(false);
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(false);
     }
 
     /**
@@ -22442,8 +21946,6 @@
             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
             notifyEnterOrExitForAutoFillIfNeeded(true);
         }
-
-        notifyAppearedOrDisappearedForContentCaptureIfNeeded(true);
     }
 
     private boolean hasParentWantsFocus() {
@@ -28650,23 +28152,6 @@
         View mTooltipHost;
 
         /**
-         * The initial structure has been reported so the view is ready to report updates.
-         */
-        boolean mReadyForContentCaptureUpdates;
-
-        /**
-         * Map(keyed by session) of content capture events that need to be notified after the view
-         * hierarchy is traversed: value is either the view itself for appearead events, or its
-         * autofill id for disappeared.
-         */
-        SparseArray<ArrayList<Object>> mContentCaptureEvents;
-
-        /**
-         * Cached reference to the {@link ContentCaptureManager}.
-         */
-        ContentCaptureManager mContentCaptureManager;
-
-        /**
          * Creates a new set of attachment information with the specified
          * events handler and thread.
          *
@@ -28684,31 +28169,6 @@
             mRootCallbacks = effectPlayer;
             mTreeObserver = new ViewTreeObserver(context);
         }
-
-        private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
-                @NonNull View view, boolean appeared) {
-            if (mContentCaptureEvents == null) {
-                // Most of the time there will be just one session, so intial capacity is 1
-                mContentCaptureEvents = new SparseArray<>(1);
-            }
-            int sessionId = session.getId();
-            // TODO: life would be much easier if we provided a MultiMap implementation somwhere...
-            ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
-            if (events == null) {
-                events = new ArrayList<>();
-                mContentCaptureEvents.put(sessionId, events);
-            }
-            events.add(appeared ? view : view.getAutofillId());
-        }
-
-        @Nullable
-        ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
-            if (mContentCaptureManager != null) {
-                return mContentCaptureManager;
-            }
-            mContentCaptureManager = context.getSystemService(ContentCaptureManager.class);
-            return mContentCaptureManager;
-        }
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 937bd1b..d362024 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3606,7 +3606,7 @@
             return;
         }
 
-        final ChildListForAutoFillOrContentCapture children = getChildrenForAutofill(flags);
+        final ChildListForAutofill children = getChildrenForAutofill(flags);
         final int childrenCount = children.size();
         structure.setChildCount(childrenCount);
         for (int i = 0; i < childrenCount; i++) {
@@ -3617,30 +3617,14 @@
         children.recycle();
     }
 
-    /** @hide */
-    @Override
-    public void dispatchProvideContentCaptureStructure() {
-        super.dispatchProvideContentCaptureStructure();
-
-        if (!isLaidOut()) return;
-
-        final ChildListForAutoFillOrContentCapture children = getChildrenForContentCapture();
-        final int childrenCount = children.size();
-        for (int i = 0; i < childrenCount; i++) {
-            final View child = children.get(i);
-            child.dispatchProvideContentCaptureStructure();
-        }
-        children.recycle();
-    }
-
     /**
      * Gets the children for autofill. Children for autofill are the first
      * level descendants that are important for autofill. The returned
      * child list object is pooled and the caller must recycle it once done.
      * @hide */
-    private @NonNull ChildListForAutoFillOrContentCapture getChildrenForAutofill(
+    private @NonNull ChildListForAutofill getChildrenForAutofill(
             @AutofillFlags int flags) {
-        final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
+        final ChildListForAutofill children = ChildListForAutofill
                 .obtain();
         populateChildrenForAutofill(children, flags);
         return children;
@@ -3668,34 +3652,6 @@
         }
     }
 
-    private @NonNull ChildListForAutoFillOrContentCapture getChildrenForContentCapture() {
-        final ChildListForAutoFillOrContentCapture children = ChildListForAutoFillOrContentCapture
-                .obtain();
-        populateChildrenForContentCapture(children);
-        return children;
-    }
-
-    /** @hide */
-    private void populateChildrenForContentCapture(ArrayList<View> list) {
-        final int childrenCount = mChildrenCount;
-        if (childrenCount <= 0) {
-            return;
-        }
-        final ArrayList<View> preorderedList = buildOrderedChildList();
-        final boolean customOrder = preorderedList == null
-                && isChildrenDrawingOrderEnabled();
-        for (int i = 0; i < childrenCount; i++) {
-            final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
-            final View child = (preorderedList == null)
-                    ? mChildren[childIndex] : preorderedList.get(childIndex);
-            if (child.isImportantForContentCapture()) {
-                list.add(child);
-            } else if (child instanceof ViewGroup) {
-                ((ViewGroup) child).populateChildrenForContentCapture(list);
-            }
-        }
-    }
-
     private static View getAndVerifyPreorderedView(ArrayList<View> preorderedList, View[] children,
             int childIndex) {
         final View child;
@@ -8678,16 +8634,16 @@
     /**
      * Pooled class that to hold the children for autifill.
      */
-    private static class ChildListForAutoFillOrContentCapture extends ArrayList<View> {
+    private static class ChildListForAutofill extends ArrayList<View> {
         private static final int MAX_POOL_SIZE = 32;
 
-        private static final Pools.SimplePool<ChildListForAutoFillOrContentCapture> sPool =
+        private static final Pools.SimplePool<ChildListForAutofill> sPool =
                 new Pools.SimplePool<>(MAX_POOL_SIZE);
 
-        public static ChildListForAutoFillOrContentCapture obtain() {
-            ChildListForAutoFillOrContentCapture list = sPool.acquire();
+        public static ChildListForAutofill obtain() {
+            ChildListForAutofill list = sPool.acquire();
             if (list == null) {
-                list = new ChildListForAutoFillOrContentCapture();
+                list = new ChildListForAutofill();
             }
             return list;
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f3b7ad5..7ad118e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -105,11 +105,7 @@
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.Interpolator;
-import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
-import android.view.contentcapture.MainContentCaptureSession;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Scroller;
 
@@ -224,21 +220,6 @@
      */
     static final int MAX_TRACKBALL_DELAY = 250;
 
-    /**
-     * Initial value for {@link #mContentCaptureEnabled}.
-     */
-    private static final int CONTENT_CAPTURE_ENABLED_NOT_CHECKED = 0;
-
-    /**
-     * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code true}.
-     */
-    private static final int CONTENT_CAPTURE_ENABLED_TRUE = 1;
-
-    /**
-     * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code false}.
-     */
-    private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
-
     @UnsupportedAppUsage
     static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
 
@@ -435,10 +416,6 @@
     boolean mLayoutRequested;
     boolean mFirst;
 
-    @Nullable
-    int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
-    boolean mPerformContentCapture;
-
     boolean mReportNextDraw;
     boolean mFullRedrawNeeded;
     boolean mNewSurfaceNeeded;
@@ -637,7 +614,6 @@
         mTransparentRegion = new Region();
         mPreviousTransparentRegion = new Region();
         mFirst = true; // true for the first time the view is added
-        mPerformContentCapture = true; // also true for the first time the view is added
         mAdded = false;
         mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
                 context);
@@ -2787,55 +2763,9 @@
             }
         }
 
-        if (mAttachInfo.mContentCaptureEvents != null) {
-            notifyContentCatpureEvents();
-        }
-
         mIsInTraversal = false;
     }
 
-    private void notifyContentCatpureEvents() {
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
-        try {
-            MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
-                    .getMainContentCaptureSession();
-            for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
-                int sessionId = mAttachInfo.mContentCaptureEvents.keyAt(i);
-                mainSession.notifyViewTreeEvent(sessionId, /* started= */ true);
-                ArrayList<Object> events = mAttachInfo.mContentCaptureEvents
-                        .valueAt(i);
-                for_each_event: for (int j = 0; j < events.size(); j++) {
-                    Object event = events.get(j);
-                    if (event instanceof AutofillId) {
-                        mainSession.notifyViewDisappeared(sessionId, (AutofillId) event);
-                    } else if (event instanceof View) {
-                        View view = (View) event;
-                        ContentCaptureSession session = view.getContentCaptureSession();
-                        if (session == null) {
-                            Log.w(mTag, "no content capture session on view: " + view);
-                            continue for_each_event;
-                        }
-                        int actualId = session.getId();
-                        if (actualId != sessionId) {
-                            Log.w(mTag, "content capture session mismatch for view (" + view
-                                    + "): was " + sessionId + " before, it's " + actualId + " now");
-                            continue for_each_event;
-                        }
-                        ViewStructure structure = session.newViewStructure(view);
-                        view.onProvideContentCaptureStructure(structure, /* flags= */ 0);
-                        session.notifyViewAppeared(structure);
-                    } else {
-                        Log.w(mTag, "invalid content capture event: " + event);
-                    }
-                }
-                mainSession.notifyViewTreeEvent(sessionId, /* started= */ false);
-            }
-            mAttachInfo.mContentCaptureEvents = null;
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-    }
-
     private void notifySurfaceDestroyed() {
         mSurfaceHolder.ungetCallbacks();
         SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
@@ -2966,13 +2896,6 @@
             }
         }
         mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
-
-        // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
-        // is lost, so we don't need to to force a flush - there might be other events such as
-        // text changes, but these should be flushed independently.
-        if (hasWindowFocus) {
-            handleContentCaptureFlush();
-        }
     }
 
     private void fireAccessibilityFocusEventIfHasFocusedNode() {
@@ -3539,86 +3462,6 @@
                 pendingDrawFinished();
             }
         }
-        if (mPerformContentCapture) {
-            performContentCaptureInitialReport();
-        }
-    }
-
-    /**
-     * Checks (and caches) if content capture is enabled for this context.
-     */
-    private boolean isContentCaptureEnabled() {
-        switch (mContentCaptureEnabled) {
-            case CONTENT_CAPTURE_ENABLED_TRUE:
-                return true;
-            case CONTENT_CAPTURE_ENABLED_FALSE:
-                return false;
-            case CONTENT_CAPTURE_ENABLED_NOT_CHECKED:
-                final boolean reallyEnabled = isContentCaptureReallyEnabled();
-                mContentCaptureEnabled = reallyEnabled ? CONTENT_CAPTURE_ENABLED_TRUE
-                        : CONTENT_CAPTURE_ENABLED_FALSE;
-                return reallyEnabled;
-            default:
-                Log.w(TAG, "isContentCaptureEnabled(): invalid state " + mContentCaptureEnabled);
-                return false;
-        }
-
-    }
-
-    /**
-     * Checks (without caching) if content capture is enabled for this context.
-     */
-    private boolean isContentCaptureReallyEnabled() {
-        // First check if context supports it, so it saves a service lookup when it doesn't
-        if (mContext.getContentCaptureOptions() == null) return false;
-
-        final ContentCaptureManager ccm = mAttachInfo.getContentCaptureManager(mContext);
-        // Then check if it's enabled in the contex itself.
-        if (ccm == null || !ccm.isContentCaptureEnabled()) return false;
-
-        return true;
-    }
-
-    private void performContentCaptureInitialReport() {
-        mPerformContentCapture = false; // One-time offer!
-        final View rootView = mView;
-        if (DEBUG_CONTENT_CAPTURE) {
-            Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
-        }
-        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
-            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
-                    + getClass().getSimpleName());
-        }
-        try {
-            if (!isContentCaptureEnabled()) return;
-
-            // Content capture is a go!
-            rootView.dispatchInitialProvideContentCaptureStructure();
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
-    }
-
-    private void handleContentCaptureFlush() {
-        if (DEBUG_CONTENT_CAPTURE) {
-            Log.v(mTag, "handleContentCaptureFlush()");
-        }
-        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
-            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
-                    + getClass().getSimpleName());
-        }
-        try {
-            if (!isContentCaptureEnabled()) return;
-
-            final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
-            if (ccm == null) {
-                Log.w(TAG, "No ContentCapture on AttachInfo");
-                return;
-            }
-            ccm.flush(ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-        }
     }
 
     private boolean draw(boolean fullRedrawNeeded) {
@@ -3986,6 +3829,24 @@
     }
 
     /**
+     * Set the root-level system gesture exclusion rects. These are added to those provided by
+     * the root's view hierarchy.
+     */
+    public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+        mGestureExclusionTracker.setRootSystemGestureExclusionRects(rects);
+        mHandler.sendEmptyMessage(MSG_SYSTEM_GESTURE_EXCLUSION_CHANGED);
+    }
+
+    /**
+     * Returns the root-level system gesture exclusion rects. These do not include those provided by
+     * the root's view hierarchy.
+     */
+    @NonNull
+    public List<Rect> getRootSystemGestureExclusionRects() {
+        return mGestureExclusionTracker.getRootSystemGestureExclusionRects();
+    }
+
+    /**
      * Requests that the root render node is invalidated next time we perform a draw, such that
      * {@link WindowCallbacks#onPostDraw} gets called.
      */
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index fc9d8c2..b0ec621 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -48,6 +48,7 @@
 import android.transition.TransitionManager;
 import android.view.accessibility.AccessibilityEvent;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -2397,6 +2398,53 @@
         return false;
     }
 
+    /**
+     * Sets a list of areas within this window's coordinate space where the system should not
+     * intercept touch or other pointing device gestures.
+     *
+     * <p>This method should be used by apps that make use of
+     * {@link #takeSurface(SurfaceHolder.Callback2)} and do not have a view hierarchy available.
+     * Apps that do have a view hierarchy should use
+     * {@link View#setSystemGestureExclusionRects(List)} instead. This method does not modify or
+     * replace the gesture exclusion rects populated by individual views in this window's view
+     * hierarchy using {@link View#setSystemGestureExclusionRects(List)}.</p>
+     *
+     * <p>Use this to tell the system which specific sub-areas of a view need to receive gesture
+     * input in order to function correctly in the presence of global system gestures that may
+     * conflict. For example, if the system wishes to capture swipe-in-from-screen-edge gestures
+     * to provide system-level navigation functionality, a view such as a navigation drawer
+     * container can mark the left (or starting) edge of itself as requiring gesture capture
+     * priority using this API. The system may then choose to relax its own gesture recognition
+     * to allow the app to consume the user's gesture. It is not necessary for an app to register
+     * exclusion rects for broadly spanning regions such as the entirety of a
+     * <code>ScrollView</code> or for simple press and release click targets such as
+     * <code>Button</code>. Mark an exclusion rect when interacting with a view requires
+     * a precision touch gesture in a small area in either the X or Y dimension, such as
+     * an edge swipe or dragging a <code>SeekBar</code> thumb.</p>
+     *
+     * <p>Do not modify the provided list after this method is called.</p>
+     *
+     * @param rects A list of precision gesture regions that this window needs to function correctly
+     */
+    @SuppressWarnings("unused")
+    public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+        throw new UnsupportedOperationException("window does not support gesture exclusion rects");
+    }
+
+    /**
+     * Retrieve the list of areas within this window's coordinate space where the system should not
+     * intercept touch or other pointing device gestures. This is the list as set by
+     * {@link #setSystemGestureExclusionRects(List)} or an empty list if
+     * {@link #setSystemGestureExclusionRects(List)} has not been called. It does not include
+     * exclusion rects set by this window's view hierarchy.
+     *
+     * @return a list of system gesture exclusion rects specific to this window
+     */
+    @NonNull
+    public List<Rect> getSystemGestureExclusionRects() {
+        return Collections.emptyList();
+    }
+
     /** @hide */
     public void setTheme(int resId) {
     }
diff --git a/core/java/android/view/autofill/AutofillManagerInternal.java b/core/java/android/view/autofill/AutofillManagerInternal.java
index 3de1a03..a07d46d 100644
--- a/core/java/android/view/autofill/AutofillManagerInternal.java
+++ b/core/java/android/view/autofill/AutofillManagerInternal.java
@@ -45,4 +45,12 @@
     @Nullable
     public abstract AutofillOptions getAutofillOptions(@NonNull String packageName,
             long versionCode, @UserIdInt int userId);
+
+    /**
+     * Checks whether the given {@code uid} owns the
+     * {@link android.service.autofill.augmented.AugmentedAutofillService} implementation associated
+     * with the given {@code userId}.
+     */
+    public abstract boolean isAugmentedAutofillServiceForUser(@NonNull int callingUid,
+            @UserIdInt int userId);
 }
diff --git a/core/java/android/view/contentcapture/ContentCaptureCondition.java b/core/java/android/view/contentcapture/ContentCaptureCondition.java
index 6f9d4d3..54ebf55 100644
--- a/core/java/android/view/contentcapture/ContentCaptureCondition.java
+++ b/core/java/android/view/contentcapture/ContentCaptureCondition.java
@@ -35,7 +35,8 @@
 public final class ContentCaptureCondition implements Parcelable {
 
     /**
-     * When set, package should use the {@link LocusId#getId()} as a regular expression.
+     * When set, package should use the {@link LocusId#getId()} as a regular expression (using the
+     * {@link java.util.regex.Pattern} format).
      */
     public static final int FLAG_IS_REGEX = 0x2;
 
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 2539356..26454c0 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -191,8 +191,8 @@
  *
  * <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws
  * the HTML using {@link Canvas} or native libraries in a different render process), then the view
- * is also responsible to notify the session when the virtual elements appear and disappear - see
- * {@link View#onProvideContentCaptureStructure(ViewStructure, int)} for more info.
+ * is also responsible to notify the session when the virtual elements appear and disappear -
+ * see {@link ContentCaptureSession#newViewStructure(View)} for more info.
  */
 @SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
 public final class ContentCaptureManager {
@@ -343,15 +343,6 @@
     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");
@@ -578,16 +569,15 @@
     }
 
     /**
-     * Called by the app to request the content capture service to remove user-data associated with
-     * some context.
+     * Called by the app to remove content capture data associated with some context.
      *
-     * @param request object specifying what user data should be removed.
+     * @param request object specifying what data should be removed.
      */
-    public void removeUserData(@NonNull UserDataRemovalRequest request) {
+    public void removeData(@NonNull DataRemovalRequest request) {
         Preconditions.checkNotNull(request);
 
         try {
-            mService.removeUserData(request);
+            mService.removeData(request);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 7761038..17a1fb4 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -356,10 +356,6 @@
     /**
      * Notifies the Content Capture Service that a node has been added to the view structure.
      *
-     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
-     * automatically by the Android System for views that return {@code true} on
-     * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
-     *
      * @param node node that has been added.
      */
     public final void notifyViewAppeared(@NonNull ViewStructure node) {
@@ -378,9 +374,6 @@
     /**
      * Notifies the Content Capture Service that a node has been removed from the view structure.
      *
-     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
-     * automatically by the Android System for standard views.
-     *
      * @param id id of the node that has been removed.
      */
     public final void notifyViewDisappeared(@NonNull AutofillId id) {
@@ -441,7 +434,46 @@
     /**
      * Creates a {@link ViewStructure} for a "standard" view.
      *
-     * @hide
+     * <p>This method should be called after a visible view is laid out; the view then must populate
+     * the structure and pass it to {@link #notifyViewAppeared(ViewStructure)}.
+     *
+     * <b>Note: </b>views that manage a virtual structure under this view must populate just the
+     * node representing this view and return right away, then asynchronously report (not
+     * necessarily in the UI thread) when the children nodes appear, disappear or have their text
+     * changed by calling {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)},
+     * {@link ContentCaptureSession#notifyViewDisappeared(AutofillId)}, and
+     * {@link ContentCaptureSession#notifyViewTextChanged(AutofillId, CharSequence)} respectively.
+     * The structure for the a child must be created using
+     * {@link ContentCaptureSession#newVirtualViewStructure(AutofillId, long)}, and the
+     * {@code autofillId} for a child can be obtained either through
+     * {@code childStructure.getAutofillId()} or
+     * {@link ContentCaptureSession#newAutofillId(AutofillId, long)}.
+     *
+     * <p>When the virtual view hierarchy represents a web page, you should also:
+     *
+     * <ul>
+     * <li>Call {@link ContentCaptureManager#getContentCaptureConditions()} to infer content capture
+     * events should be generate for that URL.
+     * <li>Create a new {@link ContentCaptureSession} child for every HTML element that renders a
+     * new URL (like an {@code IFRAME}) and use that session to notify events from that subtree.
+     * </ul>
+     *
+     * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+     * <ul>
+     * <li>{@link ViewStructure#setChildCount(int)}
+     * <li>{@link ViewStructure#addChildCount(int)}
+     * <li>{@link ViewStructure#getChildCount()}
+     * <li>{@link ViewStructure#newChild(int)}
+     * <li>{@link ViewStructure#asyncNewChild(int)}
+     * <li>{@link ViewStructure#asyncCommit()}
+     * <li>{@link ViewStructure#setWebDomain(String)}
+     * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+     * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+     * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+     * <li>{@link ViewStructure#setAlpha(float)}
+     * <li>{@link ViewStructure#setElevation(float)}
+     * <li>{@link ViewStructure#setTransformation(android.graphics.Matrix)}
+     * </ul>
      */
     @NonNull
     public final ViewStructure newViewStructure(@NonNull View view) {
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
similarity index 94%
rename from core/java/android/view/contentcapture/UserDataRemovalRequest.aidl
rename to core/java/android/view/contentcapture/DataRemovalRequest.aidl
index fbe47e0..c89d222 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.aidl
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.aidl
@@ -16,4 +16,4 @@
 
 package android.view.contentcapture;
 
-parcelable UserDataRemovalRequest;
+parcelable DataRemovalRequest;
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/DataRemovalRequest.java
similarity index 82%
rename from core/java/android/view/contentcapture/UserDataRemovalRequest.java
rename to core/java/android/view/contentcapture/DataRemovalRequest.java
index 3e1e4ab..3792846b 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.java
@@ -31,14 +31,12 @@
 import java.util.List;
 
 /**
- * Class used by apps to request the Content Capture service to remove user-data associated with
- * some context.
+ * Class used by apps to remove content capture data associated with {@link LocusId LocusIds}.
  */
-public final class UserDataRemovalRequest implements Parcelable {
+public final class DataRemovalRequest implements Parcelable {
 
     /**
-     * When set, service should use the {@link LocusId#getId()} as prefix for the data to be
-     * removed.
+     * When set, the {@link LocusId#getId()} is the prefix for the data to be removed.
      */
     public static final int FLAG_IS_PREFIX = 0x1;
 
@@ -54,7 +52,7 @@
     private final boolean mForEverything;
     private ArrayList<LocusIdRequest> mLocusIdRequests;
 
-    private UserDataRemovalRequest(@NonNull Builder builder) {
+    private DataRemovalRequest(@NonNull Builder builder) {
         mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName();
         mForEverything = builder.mForEverything;
         if (builder.mLocusIds != null) {
@@ -67,7 +65,7 @@
         }
     }
 
-    private UserDataRemovalRequest(@NonNull Parcel parcel) {
+    private DataRemovalRequest(@NonNull Parcel parcel) {
         mPackageName = parcel.readString();
         mForEverything = parcel.readBoolean();
         if (!mForEverything) {
@@ -89,7 +87,7 @@
     }
 
     /**
-     * Checks if app is requesting to remove all user data associated with its package.
+     * Checks if app is requesting to remove content capture data associated with its package.
      */
     public boolean isForEverything() {
         return mForEverything;
@@ -104,7 +102,7 @@
     }
 
     /**
-     * Builder for {@link UserDataRemovalRequest} objects.
+     * Builder for {@link DataRemovalRequest} objects.
      */
     public static final class Builder {
 
@@ -115,7 +113,7 @@
         private boolean mDestroyed;
 
         /**
-         * Requests servive to remove all user data associated with the app's package.
+         * Requests to remove all content capture data associated with the app's package.
          *
          * @return this builder
          */
@@ -132,7 +130,7 @@
          * Request service to remove data associated with a given {@link LocusId}.
          *
          * @param locusId the {@link LocusId} being requested to be removed.
-         * @param flags either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
+         * @param flags either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}
          *
          * @return this builder
          */
@@ -154,17 +152,17 @@
         }
 
         /**
-         * Builds the {@link UserDataRemovalRequest}.
+         * Builds the {@link DataRemovalRequest}.
          */
         @NonNull
-        public UserDataRemovalRequest build() {
+        public DataRemovalRequest build() {
             throwIfDestroyed();
 
             Preconditions.checkState(mForEverything || mLocusIds != null,
                     "must call either #forEverything() or add one #addLocusId()");
 
             mDestroyed = true;
-            return new UserDataRemovalRequest(this);
+            return new DataRemovalRequest(this);
         }
 
         private void throwIfDestroyed() {
@@ -192,19 +190,19 @@
         }
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<UserDataRemovalRequest> CREATOR =
-            new Parcelable.Creator<UserDataRemovalRequest>() {
+    public static final @android.annotation.NonNull Parcelable.Creator<DataRemovalRequest> CREATOR =
+            new Parcelable.Creator<DataRemovalRequest>() {
 
         @Override
         @NonNull
-        public UserDataRemovalRequest createFromParcel(Parcel parcel) {
-            return new UserDataRemovalRequest(parcel);
+        public DataRemovalRequest createFromParcel(Parcel parcel) {
+            return new DataRemovalRequest(parcel);
         }
 
         @Override
         @NonNull
-        public UserDataRemovalRequest[] newArray(int size) {
-            return new UserDataRemovalRequest[size];
+        public DataRemovalRequest[] newArray(int size) {
+            return new DataRemovalRequest[size];
         }
     };
 
@@ -231,7 +229,7 @@
         /**
          * Gets the flags associates with request.
          *
-         * @return either {@link UserDataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
+         * @return either {@link DataRemovalRequest#FLAG_IS_PREFIX} or {@code 0}.
          */
         @NonNull
         public @Flags int getFlags() {
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 7335073..ced9417 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -19,7 +19,7 @@
 import android.content.ComponentName;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureEvent;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
 import android.os.IBinder;
 
 import com.android.internal.os.IResultReceiver;
@@ -59,9 +59,9 @@
     void getServiceComponentName(in IResultReceiver result);
 
     /**
-     * Requests the removal of user data for the calling user.
+     * Requests the removal of content capture data for the calling user.
      */
-    void removeUserData(in UserDataRemovalRequest request);
+    void removeData(in DataRemovalRequest request);
 
     /**
      * Returns whether the content capture feature is enabled for the calling user.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5e00425..fd73856 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1951,6 +1951,23 @@
     }
 
     /**
+     * Unregister for IME state callbacks and applying visibility in
+     * {@link android.view.ImeInsetsSourceConsumer}.
+     * @hide
+     */
+    public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
+        if (imeInsetsConsumer == null) {
+            throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
+        }
+
+        synchronized (mH) {
+            if (mImeInsetsConsumer == imeInsetsConsumer) {
+                mImeInsetsConsumer = null;
+            }
+        }
+    }
+
+    /**
      * Call showSoftInput with currently focused view.
      * @return {@code true} if IME can be shown.
      * @hide
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index b408129..f2fa67d 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -316,16 +316,20 @@
         private final List<String> mHints;
         @Nullable
         private String mCallingPackageName;
+        @NonNull
+        private Bundle mExtras;
 
         private Request(
                 @NonNull List<Message> conversation,
                 @NonNull TextClassifier.EntityConfig typeConfig,
                 int maxSuggestions,
-                @Nullable @Hint List<String> hints) {
+                @Nullable @Hint List<String> hints,
+                @NonNull Bundle extras) {
             mConversation = Preconditions.checkNotNull(conversation);
             mTypeConfig = Preconditions.checkNotNull(typeConfig);
             mMaxSuggestions = maxSuggestions;
             mHints = hints;
+            mExtras = extras;
         }
 
         private static Request readFromParcel(Parcel in) {
@@ -336,12 +340,13 @@
             List<String> hints = new ArrayList<>();
             in.readStringList(hints);
             String callingPackageName = in.readString();
-
+            Bundle extras = in.readBundle();
             Request request = new Request(
                     conversation,
                     typeConfig,
                     maxSuggestions,
-                    hints);
+                    hints,
+                    extras);
             request.setCallingPackageName(callingPackageName);
             return request;
         }
@@ -353,6 +358,7 @@
             parcel.writeInt(mMaxSuggestions);
             parcel.writeStringList(mHints);
             parcel.writeString(mCallingPackageName);
+            parcel.writeBundle(mExtras);
         }
 
         @Override
@@ -421,6 +427,16 @@
             return mCallingPackageName;
         }
 
+        /**
+         * Returns the extended data related to this request.
+         *
+         * <p><b>NOTE: </b>Do not modify this bundle.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras;
+        }
+
         /** Builder object to construct the {@link Request} object. */
         public static final class Builder {
             @NonNull
@@ -431,6 +447,8 @@
             @Nullable
             @Hint
             private List<String> mHints;
+            @Nullable
+            private Bundle mExtras;
 
             /**
              * Constructs a builder.
@@ -469,6 +487,13 @@
                 return this;
             }
 
+            /** Sets a set of extended data to the request. */
+            @NonNull
+            public Builder setExtras(@Nullable Bundle bundle) {
+                mExtras = bundle;
+                return this;
+            }
+
             /** Builds the {@link Request} object. */
             @NonNull
             public Request build() {
@@ -480,7 +505,8 @@
                         mMaxSuggestions,
                         mHints == null
                                 ? Collections.emptyList()
-                                : Collections.unmodifiableList(mHints));
+                                : Collections.unmodifiableList(mHints),
+                        mExtras == null ? Bundle.EMPTY : mExtras);
             }
         }
     }
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index 7b23674..11e0e2c 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -36,6 +36,7 @@
 // TODO: Make this a TestApi for CTS testing.
 public final class ExtrasUtils {
 
+    // Keys for response objects.
     private static final String SERIALIZED_ENTITIES_DATA = "serialized-entities-data";
     private static final String ENTITIES_EXTRAS = "entities-extras";
     private static final String ACTION_INTENT = "action-intent";
@@ -48,6 +49,10 @@
     private static final String TEXT_LANGUAGES = "text-languages";
     private static final String ENTITIES = "entities";
 
+    // Keys for request objects.
+    private static final String IS_SERIALIZED_ENTITY_DATA_ENABLED =
+            "is-serialized-entity-data-enabled";
+
     private ExtrasUtils() {}
 
     /**
@@ -308,7 +313,23 @@
     /**
      * Returns a list of entities contained in the {@code extra}.
      */
+    @Nullable
     public static List<Bundle> getEntities(Bundle container) {
         return container.getParcelableArrayList(ENTITIES);
     }
+
+    /**
+     * Whether the annotator should populate serialized entity data into the result object.
+     */
+    public static boolean isSerializedEntityDataEnabled(TextLinks.Request request) {
+        return request.getExtras().getBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED);
+    }
+
+    /**
+     * To indicate whether the annotator should populate serialized entity data in the result
+     * object.
+     */
+    public static void putIsSerializedEntityDataEnabled(Bundle bundle, boolean isEnabled) {
+        bundle.putBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED, isEnabled);
+    }
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 236f89b..d3d61a7 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.icu.util.ULocale;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,54 +31,65 @@
 import java.util.Arrays;
 
 /**
- * A text classifier event.
+ * This class represents events that are sent by components to the {@link TextClassifier} to report
+ * something of note that relates to a feature powered by the TextClassifier. The TextClassifier may
+ * log these events or use them to improve future responses to queries.
+ * <p>
+ * Each categories of the events have their own subclass. Events of each types has an associated
+ * set of related properties. You can find the specification of them in the subclasses.
  */
-// TODO: Comprehensive javadoc.
-public final class TextClassifierEvent implements Parcelable {
+public abstract class TextClassifierEvent implements Parcelable {
 
-    public static final @android.annotation.NonNull Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
-        @Override
-        public TextClassifierEvent createFromParcel(Parcel in) {
-            return readFromParcel(in);
-        }
-
-        @Override
-        public TextClassifierEvent[] newArray(int size) {
-            return new TextClassifierEvent[size];
-        }
-    };
+    private static final int PARCEL_TOKEN_TEXT_SELECTION_EVENT = 1;
+    private static final int PARCEL_TOKEN_TEXT_LINKIFY_EVENT = 2;
+    private static final int PARCEL_TOKEN_CONVERSATION_ACTION_EVENT = 3;
+    private static final int PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT = 4;
 
     /** @hide **/
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({CATEGORY_UNDEFINED, CATEGORY_SELECTION, CATEGORY_LINKIFY,
+    @IntDef({CATEGORY_SELECTION, CATEGORY_LINKIFY,
             CATEGORY_CONVERSATION_ACTIONS, CATEGORY_LANGUAGE_DETECTION})
     public @interface Category {
         // For custom event categories, use range 1000+.
     }
-    /** Undefined category */
-    public static final int CATEGORY_UNDEFINED = 0;
-    /** Smart selection */
+
+    /**
+     * Smart selection
+     *
+     * @see TextSelectionEvent
+     */
     public static final int CATEGORY_SELECTION = 1;
-    /** Linkify */
+    /**
+     * Linkify
+     *
+     * @see TextLinkifyEvent
+     */
     public static final int CATEGORY_LINKIFY = 2;
-    /** Conversation actions */
+    /**
+     *  Conversation actions
+     *
+     * @see ConversationActionsEvent
+     */
     public static final int CATEGORY_CONVERSATION_ACTIONS = 3;
-    /** Language detection */
+    /**
+     * Language detection
+     *
+     * @see LanguageDetectionEvent
+     */
     public static final int CATEGORY_LANGUAGE_DETECTION = 4;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({TYPE_UNDEFINED, TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
-             TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
-             TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
-             TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
-             TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
-             TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
+    @IntDef({TYPE_SELECTION_STARTED, TYPE_SELECTION_MODIFIED,
+            TYPE_SMART_SELECTION_SINGLE, TYPE_SMART_SELECTION_MULTI, TYPE_AUTO_SELECTION,
+            TYPE_ACTIONS_SHOWN, TYPE_LINK_CLICKED, TYPE_OVERTYPE, TYPE_COPY_ACTION,
+            TYPE_PASTE_ACTION, TYPE_CUT_ACTION, TYPE_SHARE_ACTION, TYPE_SMART_ACTION,
+            TYPE_SELECTION_DRAG, TYPE_SELECTION_DESTROYED, TYPE_OTHER_ACTION, TYPE_SELECT_ALL,
+            TYPE_SELECTION_RESET, TYPE_MANUAL_REPLY, TYPE_ACTIONS_GENERATED})
     public @interface Type {
         // For custom event types, use range 1,000,000+.
     }
-    /** User started a new selection. */
-    public static final int TYPE_UNDEFINED = 0;
+
     /** User started a new selection. */
     public static final int TYPE_SELECTION_STARTED = 1;
     /** User modified an existing selection. */
@@ -119,63 +131,49 @@
     /** TextClassifier generated some actions */
     public static final int TYPE_ACTIONS_GENERATED = 20;
 
-    @Category private final int mEventCategory;
-    @Type private final int mEventType;
-    @Nullable private final String[] mEntityTypes;
-    @Nullable private final TextClassificationContext mEventContext;
-    @Nullable private final String mResultId;
+    @Category
+    private final int mEventCategory;
+    @Type
+    private final int mEventType;
+    @Nullable
+    private final String[] mEntityTypes;
+    @Nullable
+    private final TextClassificationContext mEventContext;
+    @Nullable
+    private final String mResultId;
     private final int mEventIndex;
-    private final long mEventTime;
+    private final float[] mScores;
+    @Nullable
+    private final String mModelName;
+    private final int[] mActionIndices;
     private final Bundle mExtras;
 
-    // Smart selection.
-    private final int mRelativeWordStartIndex;
-    private final int mRelativeWordEndIndex;
-    private final int mRelativeSuggestedWordStartIndex;
-    private final int mRelativeSuggestedWordEndIndex;
+    private TextClassifierEvent(Builder builder) {
+        mEventCategory = builder.mEventCategory;
+        mEventType = builder.mEventType;
+        mEntityTypes = builder.mEntityTypes;
+        mEventContext = builder.mEventContext;
+        mResultId = builder.mResultId;
+        mEventIndex = builder.mEventIndex;
+        mScores = builder.mScores;
+        mModelName = builder.mModelName;
+        mActionIndices = builder.mActionIndices;
+        mExtras = builder.mExtras == null ? Bundle.EMPTY : builder.mExtras;
+    }
 
-    // Smart action.
-    private final int[] mActionIndices;
-
-    // Language detection.
-    @Nullable private final String mLanguage;
-    private final float mScore;
-
-    @Nullable private final String mModelName;
-
-    private TextClassifierEvent(
-            int eventCategory,
-            int eventType,
-            String[] entityTypes,
-            TextClassificationContext eventContext,
-            String resultId,
-            int eventIndex,
-            long eventTime,
-            Bundle extras,
-            int relativeWordStartIndex,
-            int relativeWordEndIndex,
-            int relativeSuggestedWordStartIndex,
-            int relativeSuggestedWordEndIndex,
-            int[] actionIndex,
-            String language,
-            float score,
-            String modelVersion) {
-        mEventCategory = eventCategory;
-        mEventType = eventType;
-        mEntityTypes = entityTypes;
-        mEventContext = eventContext;
-        mResultId = resultId;
-        mEventIndex = eventIndex;
-        mEventTime = eventTime;
-        mExtras = extras;
-        mRelativeWordStartIndex = relativeWordStartIndex;
-        mRelativeWordEndIndex = relativeWordEndIndex;
-        mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
-        mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
-        mActionIndices = actionIndex;
-        mLanguage = language;
-        mScore = score;
-        mModelName = modelVersion;
+    private TextClassifierEvent(Parcel in) {
+        mEventCategory = in.readInt();
+        mEventType = in.readInt();
+        mEntityTypes = in.readStringArray();
+        mEventContext = in.readParcelable(null);
+        mResultId = in.readString();
+        mEventIndex = in.readInt();
+        int scoresLength = in.readInt();
+        mScores = new float[scoresLength];
+        in.readFloatArray(mScores);
+        mModelName = in.readString();
+        mActionIndices = in.createIntArray();
+        mExtras = in.readBundle();
     }
 
     @Override
@@ -183,44 +181,62 @@
         return 0;
     }
 
+    @NonNull
+    public static final Creator<TextClassifierEvent> CREATOR = new Creator<TextClassifierEvent>() {
+        @Override
+        public TextClassifierEvent createFromParcel(Parcel in) {
+            int token = in.readInt();
+            if (token == PARCEL_TOKEN_TEXT_SELECTION_EVENT) {
+                return new TextSelectionEvent(in);
+            }
+            if (token == PARCEL_TOKEN_TEXT_LINKIFY_EVENT) {
+                return new TextLinkifyEvent(in);
+            }
+            if (token == PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT) {
+                return new LanguageDetectionEvent(in);
+            }
+            if (token == PARCEL_TOKEN_CONVERSATION_ACTION_EVENT) {
+                return new ConversationActionsEvent(in);
+            }
+            throw new IllegalStateException("Unexpected input event type token in parcel.");
+        }
+
+        @Override
+        public TextClassifierEvent[] newArray(int size) {
+            return new TextClassifierEvent[size];
+        }
+    };
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(getParcelToken());
         dest.writeInt(mEventCategory);
         dest.writeInt(mEventType);
         dest.writeStringArray(mEntityTypes);
         dest.writeParcelable(mEventContext, flags);
         dest.writeString(mResultId);
         dest.writeInt(mEventIndex);
-        dest.writeLong(mEventTime);
-        dest.writeBundle(mExtras);
-        dest.writeInt(mRelativeWordStartIndex);
-        dest.writeInt(mRelativeWordEndIndex);
-        dest.writeInt(mRelativeSuggestedWordStartIndex);
-        dest.writeInt(mRelativeSuggestedWordEndIndex);
-        dest.writeIntArray(mActionIndices);
-        dest.writeString(mLanguage);
-        dest.writeFloat(mScore);
+        dest.writeInt(mScores.length);
+        dest.writeFloatArray(mScores);
         dest.writeString(mModelName);
+        dest.writeIntArray(mActionIndices);
+        dest.writeBundle(mExtras);
     }
 
-    private static TextClassifierEvent readFromParcel(Parcel in) {
-        return new TextClassifierEvent(
-                /* eventCategory= */ in.readInt(),
-                /* eventType= */ in.readInt(),
-                /* entityTypes=*/ in.readStringArray(),
-                /* eventContext= */ in.readParcelable(null),
-                /* resultId= */ in.readString(),
-                /* eventIndex= */ in.readInt(),
-                /* eventTime= */ in.readLong(),
-                /* extras= */ in.readBundle(),
-                /* relativeWordStartIndex= */ in.readInt(),
-                /* relativeWordEndIndex= */ in.readInt(),
-                /* relativeSuggestedWordStartIndex= */ in.readInt(),
-                /* relativeSuggestedWordEndIndex= */ in.readInt(),
-                /* actionIndices= */ in.createIntArray(),
-                /* language= */ in.readString(),
-                /* score= */ in.readFloat(),
-                /* modelVersion= */ in.readString());
+    private int getParcelToken() {
+        if (this instanceof TextSelectionEvent) {
+            return PARCEL_TOKEN_TEXT_SELECTION_EVENT;
+        }
+        if (this instanceof TextLinkifyEvent) {
+            return PARCEL_TOKEN_TEXT_LINKIFY_EVENT;
+        }
+        if (this instanceof LanguageDetectionEvent) {
+            return PARCEL_TOKEN_LANGUAGE_DETECTION_EVENT;
+        }
+        if (this instanceof ConversationActionsEvent) {
+            return PARCEL_TOKEN_CONVERSATION_ACTION_EVENT;
+        }
+        throw new IllegalArgumentException("Unexpected type: " + this.getClass().getSimpleName());
     }
 
     /**
@@ -241,6 +257,8 @@
 
     /**
      * Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+     *
+     * @see Builder#setEntityTypes(String...) for supported types.
      */
     @NonNull
     public String[] getEntityTypes() {
@@ -270,13 +288,33 @@
         return mEventIndex;
     }
 
-    // TODO: Remove this API.
     /**
-     * Returns the time this event occurred. This is the number of milliseconds since
-     * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+     * Returns the scores of the suggestions.
      */
-    public long getEventTime() {
-        return mEventTime;
+    @NonNull
+    public float[] getScores() {
+        return mScores;
+    }
+
+    /**
+     * Returns the model name.
+     */
+    @Nullable
+    public String getModelName() {
+        return mModelName;
+    }
+
+    /**
+     * Returns the indices of the actions relating to this event.
+     * Actions are usually returned by the text classifier in priority order with the most
+     * preferred action at index 0. This list gives an indication of the position of the actions
+     * that are being reported.
+     *
+     * @see Builder#setActionIndices(int...)
+     */
+    @NonNull
+    public int[] getActionIndices() {
+        return mActionIndices;
     }
 
     /**
@@ -289,151 +327,149 @@
         return mExtras;
     }
 
-    /**
-     * For smart selection. Returns the relative word index of the start of the selection.
-     */
-    public int getRelativeWordStartIndex() {
-        return mRelativeWordStartIndex;
-    }
-
-    /**
-     * For smart selection. Returns the relative word (exclusive) index of the end of the selection.
-     */
-    public int getRelativeWordEndIndex() {
-        return mRelativeWordEndIndex;
-    }
-
-    /**
-     * For smart selection. Returns the relative word index of the start of the smart selection.
-     */
-    public int getRelativeSuggestedWordStartIndex() {
-        return mRelativeSuggestedWordStartIndex;
-    }
-
-    /**
-     * For smart selection. Returns the relative word (exclusive) index of the end of the
-     * smart selection.
-     */
-    public int getRelativeSuggestedWordEndIndex() {
-        return mRelativeSuggestedWordEndIndex;
-    }
-
-    /**
-     * Returns the indices of the actions relating to this event.
-     * Actions are usually returned by the text classifier in priority order with the most
-     * preferred action at index 0. This list gives an indication of the position of the actions
-     * that are being reported.
-     */
-    @NonNull
-    public int[] getActionIndices() {
-        return mActionIndices;
-    }
-
-    /**
-     * For language detection. Returns the language tag for the detected locale.
-     * @see java.util.Locale#forLanguageTag(String).
-     */
-    @Nullable
-    public String getLanguage() {
-        return mLanguage;
-    }
-
-    /**
-     * Returns the score of the suggestion.
-     */
-    public float getScore() {
-        return mScore;
-    }
-
-    /**
-     * Returns the model name.
-     * @hide
-     */
-    @Nullable
-    public String getModelName() {
-        return mModelName;
+    @Override
+    public String toString() {
+        StringBuilder out = new StringBuilder(128);
+        out.append(this.getClass().getSimpleName());
+        out.append("{");
+        out.append("mEventCategory=").append(mEventCategory);
+        out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
+        out.append(", mEventContext=").append(mEventContext);
+        out.append(", mResultId=").append(mResultId);
+        out.append(", mEventIndex=").append(mEventIndex);
+        out.append(", mExtras=").append(mExtras);
+        out.append(", mScores=").append(Arrays.toString(mScores));
+        out.append(", mModelName=").append(mModelName);
+        out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
+        out.append("}");
+        return out.toString();
     }
 
     /**
      * Builder to build a text classifier event.
+     *
+     * @param <T> The subclass to be built.
      */
-    public static final class Builder {
+    public abstract static class Builder<T extends Builder<T>> {
 
         private final int mEventCategory;
         private final int mEventType;
         private String[] mEntityTypes = new String[0];
-        @Nullable private TextClassificationContext mEventContext;
-        @Nullable private String mResultId;
+        @Nullable
+        private TextClassificationContext mEventContext;
+        @Nullable
+        private String mResultId;
         private int mEventIndex;
-        private long mEventTime;
-        @Nullable private Bundle mExtras;
-        private int mRelativeWordStartIndex;
-        private int mRelativeWordEndIndex;
-        private int mRelativeSuggestedWordStartIndex;
-        private int mRelativeSuggestedWordEndIndex;
-        private int[] mActionIndices = new int[0];
-        @Nullable private String mLanguage;
-        private float mScore;
-
+        private float[] mScores = new float[0];
+        @Nullable
         private String mModelName;
+        private int[] mActionIndices = new int[0];
+        @Nullable
+        private Bundle mExtras;
 
         /**
          * Creates a builder for building {@link TextClassifierEvent}s.
          *
          * @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION}
-         * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+         * @param eventType     The event type. e.g. {@link #TYPE_SELECTION_STARTED}
          */
-        public Builder(@Category int eventCategory, @Type int eventType) {
+        private Builder(@Category int eventCategory, @Type int eventType) {
             mEventCategory = eventCategory;
             mEventType = eventType;
         }
 
         /**
          * Sets the entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}.
+         * <p>
+         * Supported types:
+         * <p>See {@link TextClassifier.EntityType}
+         * <p>See {@link ConversationAction.ActionType}
+         * <p>See {@link ULocale#toLanguageTag()}
          */
         @NonNull
-        public Builder setEntityTypes(@NonNull String... entityTypes) {
+        public T setEntityTypes(@NonNull String... entityTypes) {
+            Preconditions.checkNotNull(entityTypes);
             mEntityTypes = new String[entityTypes.length];
             System.arraycopy(entityTypes, 0, mEntityTypes, 0, entityTypes.length);
-            return this;
+            return self();
         }
 
         /**
          * Sets the event context.
          */
         @NonNull
-        public Builder setEventContext(@Nullable TextClassificationContext eventContext) {
+        public T setEventContext(@Nullable TextClassificationContext eventContext) {
             mEventContext = eventContext;
-            return this;
+            return self();
         }
 
         /**
          * Sets the id of the text classifier result related to this event.
          */
         @NonNull
-        public Builder setResultId(@Nullable String resultId) {
+        public T setResultId(@Nullable String resultId) {
             mResultId = resultId;
-            return this;
+            return self();
         }
 
         /**
-         * Sets the index of this events in the series of events it belongs to.
+         * Sets the index of this event in the series of events it belongs to.
          */
         @NonNull
-        public Builder setEventIndex(int eventIndex) {
+        public T setEventIndex(int eventIndex) {
             mEventIndex = eventIndex;
-            return this;
+            return self();
         }
 
-        // TODO: Remove this API.
         /**
-         * Sets the time this event occurred. This is the number of milliseconds since
-         * January 1, 1970, 00:00:00 GMT. 0 indicates not set.
+         * Sets the scores of the suggestions.
          */
         @NonNull
-        public Builder setEventTime(long eventTime) {
-            mEventTime = eventTime;
-            return this;
+        public T setScores(@NonNull float... scores) {
+            Preconditions.checkNotNull(scores);
+            mScores = new float[scores.length];
+            System.arraycopy(scores, 0, mScores, 0, scores.length);
+            return self();
+        }
+
+        /**
+         * Sets the model name string.
+         */
+        @NonNull
+        public T setModelName(@Nullable String modelVersion) {
+            mModelName = modelVersion;
+            return self();
+        }
+
+        /**
+         * Sets the indices of the actions involved in this event. Actions are usually returned by
+         * the text classifier in priority order with the most preferred action at index 0.
+         * These indices give an indication of the position of the actions that are being reported.
+         * <p>
+         * E.g.
+         * <pre>
+         *   // 3 smart actions are shown at index 0, 1, 2 respectively in response to a link click.
+         *   new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_ACTIONS_SHOWN)
+         *       .setEventIndex(0, 1, 2)
+         *       ...
+         *       .build();
+         *
+         *   ...
+         *
+         *   // Smart action at index 1 is activated.
+         *   new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_SMART_ACTION)
+         *       .setEventIndex(1)
+         *       ...
+         *       .build();
+         * </pre>
+         *
+         * @see TextClassification#getActions()
+         */
+        @NonNull
+        public T setActionIndices(@NonNull int... actionIndices) {
+            mActionIndices = new int[actionIndices.length];
+            System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
+            return self();
         }
 
         /**
@@ -445,136 +481,545 @@
          * objects in this bundle.
          */
         @NonNull
-        public Builder setExtras(@NonNull Bundle extras) {
+        public T setExtras(@NonNull Bundle extras) {
             mExtras = Preconditions.checkNotNull(extras);
-            return this;
+            return self();
         }
 
-        /**
-         * For smart selection. Sets the relative word index of the start of the selection.
-         */
-        @NonNull
-        public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
-            mRelativeWordStartIndex = relativeWordStartIndex;
-            return this;
-        }
-
-        /**
-         * For smart selection. Sets the relative word (exclusive) index of the end of the
-         * selection.
-         */
-        @NonNull
-        public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
-            mRelativeWordEndIndex = relativeWordEndIndex;
-            return this;
-        }
-
-        /**
-         * For smart selection. Sets the relative word index of the start of the smart selection.
-         */
-        @NonNull
-        public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
-            mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
-            return this;
-        }
-
-        /**
-         * For smart selection. Sets the relative word (exclusive) index of the end of the
-         * smart selection.
-         */
-        @NonNull
-        public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
-            mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
-            return this;
-        }
-
-        /**
-         * Sets the indices of the actions involved in this event. Actions are usually returned by
-         * the text classifier in priority order with the most preferred action at index 0.
-         * This index gives an indication of the position of the action that is being reported.
-         */
-        @NonNull
-        public Builder setActionIndices(@NonNull int... actionIndices) {
-            mActionIndices = new int[actionIndices.length];
-            System.arraycopy(actionIndices, 0, mActionIndices, 0, actionIndices.length);
-            return this;
-        }
-
-        /**
-         * For language detection. Sets the language tag for the detected locale.
-         * @see java.util.Locale#forLanguageTag(String).
-         */
-        @NonNull
-        public Builder setLanguage(@Nullable String language) {
-            mLanguage = language;
-            return this;
-        }
-
-        /**
-         * Sets the score of the suggestion.
-         */
-        @NonNull
-        public Builder setScore(float score) {
-            mScore = score;
-            return this;
-        }
-
-        /**
-         * Sets the model name string.
-         * @hide
-         */
-        public Builder setModelName(@Nullable String modelVersion) {
-            mModelName = modelVersion;
-            return this;
-        }
-
-        /**
-         * Builds and returns a text classifier event.
-         */
-        @NonNull
-        public TextClassifierEvent build() {
-            mExtras = mExtras == null ? Bundle.EMPTY : mExtras;
-            return new TextClassifierEvent(
-                    mEventCategory,
-                    mEventType,
-                    mEntityTypes,
-                    mEventContext,
-                    mResultId,
-                    mEventIndex,
-                    mEventTime,
-                    mExtras,
-                    mRelativeWordStartIndex,
-                    mRelativeWordEndIndex,
-                    mRelativeSuggestedWordStartIndex,
-                    mRelativeSuggestedWordEndIndex,
-                    mActionIndices,
-                    mLanguage,
-                    mScore,
-                    mModelName);
-        }
-        // TODO: Add build(boolean validate).
+        abstract T self();
     }
 
-    @Override
-    public String toString() {
-        StringBuilder out = new StringBuilder(128);
-        out.append("TextClassifierEvent{");
-        out.append("mEventCategory=").append(mEventCategory);
-        out.append(", mEventTypes=").append(Arrays.toString(mEntityTypes));
-        out.append(", mEventContext=").append(mEventContext);
-        out.append(", mResultId=").append(mResultId);
-        out.append(", mEventIndex=").append(mEventIndex);
-        out.append(", mEventTime=").append(mEventTime);
-        out.append(", mExtras=").append(mExtras);
-        out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
-        out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
-        out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
-        out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
-        out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
-        out.append(", mLanguage=").append(mLanguage);
-        out.append(", mScore=").append(mScore);
-        out.append(", mModelName=").append(mModelName);
-        out.append("}");
-        return out.toString();
+    /**
+     * This class represents events that are related to the smart text selection feature.
+     * <p>
+     * <pre>
+     *     // User started a selection. e.g. "York" in text "New York City, NY".
+     *     new TextSelectionEvent.Builder(TYPE_SELECTION_STARTED)
+     *         .setEventContext(classificationContext)
+     *         .setEventIndex(0)
+     *         .build();
+     *
+     *     // System smart-selects a recognized entity. e.g. "New York City".
+     *     new TextSelectionEvent.Builder(TYPE_SMART_SELECTION_MULTI)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textSelection.getId())
+     *         .setRelativeWordStartIndex(-1) // Goes back one word to "New" from "York".
+     *         .setRelativeWordEndIndex(2)    // Goes forward 2 words from "York" to start of ",".
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(1)
+     *         .build();
+     *
+     *     // User resets the selection to the original selection. i.e. "York".
+     *     new TextSelectionEvent.Builder(TYPE_SELECTION_RESET)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textSelection.getId())
+     *         .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+     *         .setRelativeSuggestedWordEndIndex(2)    // Repeated from above.
+     *         .setRelativeWordStartIndex(0)           // Original selection is always at (0, 1].
+     *         .setRelativeWordEndIndex(1)
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(2)
+     *         .build();
+     *
+     *     // User modified the selection. e.g. "New".
+     *     new TextSelectionEvent.Builder(TYPE_SELECTION_MODIFIED)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textSelection.getId())
+     *         .setRelativeSuggestedWordStartIndex(-1) // Repeated from above.
+     *         .setRelativeSuggestedWordEndIndex(2)    // Repeated from above.
+     *         .setRelativeWordStartIndex(-1)          // Goes backward one word from "York" to
+     *         "New".
+     *         .setRelativeWordEndIndex(0)             // Goes backward one word to exclude "York".
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(3)
+     *         .build();
+     *
+     *     // Smart (contextual) actions (at indices, 0, 1, 2) presented to the user.
+     *     // e.g. "Map", "Ride share", "Explore".
+     *     new TextSelectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setActionIndices(0, 1, 2)
+     *         .setEventIndex(4)
+     *         .build();
+     *
+     *     // User chooses the "Copy" action.
+     *     new TextSelectionEvent.Builder(TYPE_COPY_ACTION)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(5)
+     *         .build();
+     *
+     *     // User chooses smart action at index 1. i.e. "Ride share".
+     *     new TextSelectionEvent.Builder(TYPE_SMART_ACTION)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setActionIndices(1)
+     *         .setEventIndex(5)
+     *         .build();
+     *
+     *     // Selection dismissed.
+     *     new TextSelectionEvent.Builder(TYPE_SELECTION_DESTROYED)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(6)
+     *         .build();
+     * </pre>
+     * <p>
+     */
+    public static final class TextSelectionEvent extends TextClassifierEvent implements Parcelable {
+
+        @NonNull
+        public static final Creator<TextSelectionEvent> CREATOR =
+                new Creator<TextSelectionEvent>() {
+                    @Override
+                    public TextSelectionEvent createFromParcel(Parcel in) {
+                        in.readInt(); // skip token, we already know this is a TextSelectionEvent
+                        return new TextSelectionEvent(in);
+                    }
+
+                    @Override
+                    public TextSelectionEvent[] newArray(int size) {
+                        return new TextSelectionEvent[size];
+                    }
+                };
+
+        final int mRelativeWordStartIndex;
+        final int mRelativeWordEndIndex;
+        final int mRelativeSuggestedWordStartIndex;
+        final int mRelativeSuggestedWordEndIndex;
+
+        private TextSelectionEvent(TextSelectionEvent.Builder builder) {
+            super(builder);
+            mRelativeWordStartIndex = builder.mRelativeWordStartIndex;
+            mRelativeWordEndIndex = builder.mRelativeWordEndIndex;
+            mRelativeSuggestedWordStartIndex = builder.mRelativeSuggestedWordStartIndex;
+            mRelativeSuggestedWordEndIndex = builder.mRelativeSuggestedWordEndIndex;
+        }
+
+        private TextSelectionEvent(Parcel in) {
+            super(in);
+            mRelativeWordStartIndex = in.readInt();
+            mRelativeWordEndIndex = in.readInt();
+            mRelativeSuggestedWordStartIndex = in.readInt();
+            mRelativeSuggestedWordEndIndex = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(mRelativeWordStartIndex);
+            dest.writeInt(mRelativeWordEndIndex);
+            dest.writeInt(mRelativeSuggestedWordStartIndex);
+            dest.writeInt(mRelativeSuggestedWordEndIndex);
+        }
+
+        /**
+         * Returns the relative word index of the start of the selection.
+         */
+        public int getRelativeWordStartIndex() {
+            return mRelativeWordStartIndex;
+        }
+
+        /**
+         * Returns the relative word (exclusive) index of the end of the selection.
+         */
+        public int getRelativeWordEndIndex() {
+            return mRelativeWordEndIndex;
+        }
+
+        /**
+         * Returns the relative word index of the start of the smart selection.
+         */
+        public int getRelativeSuggestedWordStartIndex() {
+            return mRelativeSuggestedWordStartIndex;
+        }
+
+        /**
+         * Returns the relative word (exclusive) index of the end of the
+         * smart selection.
+         */
+        public int getRelativeSuggestedWordEndIndex() {
+            return mRelativeSuggestedWordEndIndex;
+        }
+
+        /**
+         * Builder class for {@link TextSelectionEvent}.
+         */
+        public static final class Builder extends
+                TextClassifierEvent.Builder<TextSelectionEvent.Builder> {
+            int mRelativeWordStartIndex;
+            int mRelativeWordEndIndex;
+            int mRelativeSuggestedWordStartIndex;
+            int mRelativeSuggestedWordEndIndex;
+
+            /**
+             * Creates a builder for building {@link TextSelectionEvent}s.
+             *
+             * @param eventType     The event type. e.g. {@link #TYPE_SELECTION_STARTED}
+             */
+            public Builder(@Type int eventType) {
+                super(CATEGORY_SELECTION, eventType);
+            }
+
+            /**
+             * Sets the relative word index of the start of the selection.
+             */
+            @NonNull
+            public Builder setRelativeWordStartIndex(int relativeWordStartIndex) {
+                mRelativeWordStartIndex = relativeWordStartIndex;
+                return this;
+            }
+
+            /**
+             * Sets the relative word (exclusive) index of the end of the
+             * selection.
+             */
+            @NonNull
+            public Builder setRelativeWordEndIndex(int relativeWordEndIndex) {
+                mRelativeWordEndIndex = relativeWordEndIndex;
+                return this;
+            }
+
+            /**
+             * Sets the relative word index of the start of the smart
+             * selection.
+             */
+            @NonNull
+            public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) {
+                mRelativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex;
+                return this;
+            }
+
+            /**
+             * Sets the relative word (exclusive) index of the end of the
+             * smart selection.
+             */
+            @NonNull
+            public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) {
+                mRelativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex;
+                return this;
+            }
+
+            @Override
+            TextSelectionEvent.Builder self() {
+                return this;
+            }
+
+            /**
+             * Builds and returns a {@link TextSelectionEvent}.
+             */
+            @NonNull
+            public TextSelectionEvent build() {
+                return new TextSelectionEvent(this);
+            }
+        }
+    }
+
+    /**
+     * This class represents events that are related to the smart linkify feature.
+     * <p>
+     * <pre>
+     *     // User clicked on a link.
+     *     new TextLinkifyEvent.Builder(TYPE_LINK_CLICKED)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setEventIndex(0)
+     *         .build();
+     *
+     *     // Smart (contextual) actions presented to the user in response to a link click.
+     *     new TextLinkifyEvent.Builder(TYPE_ACTIONS_SHOWN)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setActionIndices(range(textClassification.getActions().size()))
+     *         .setEventIndex(1)
+     *         .build();
+     *
+     *     // User chooses smart action at index 0.
+     *     new TextLinkifyEvent.Builder(TYPE_SMART_ACTION)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(textClassification.getEntity(0))
+     *         .setScore(textClassification.getConfidenceScore(entityType))
+     *         .setActionIndices(0)
+     *         .setEventIndex(2)
+     *         .build();
+     * </pre>
+     */
+    public static final class TextLinkifyEvent extends TextClassifierEvent implements Parcelable {
+
+        @NonNull
+        public static final Creator<TextLinkifyEvent> CREATOR =
+                new Creator<TextLinkifyEvent>() {
+                    @Override
+                    public TextLinkifyEvent createFromParcel(Parcel in) {
+                        in.readInt(); // skip token, we already know this is a TextLinkifyEvent
+                        return new TextLinkifyEvent(in);
+                    }
+
+                    @Override
+                    public TextLinkifyEvent[] newArray(int size) {
+                        return new TextLinkifyEvent[size];
+                    }
+                };
+
+        private TextLinkifyEvent(Parcel in) {
+            super(in);
+        }
+
+        private TextLinkifyEvent(TextLinkifyEvent.Builder builder) {
+            super(builder);
+        }
+
+        /**
+         * Builder class for {@link TextLinkifyEvent}.
+         */
+        public static final class Builder
+                extends TextClassifierEvent.Builder<TextLinkifyEvent.Builder> {
+            /**
+             * Creates a builder for building {@link TextLinkifyEvent}s.
+             *
+             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+             */
+            public Builder(@Type int eventType) {
+                super(TextClassifierEvent.CATEGORY_LINKIFY, eventType);
+            }
+
+            @Override
+            Builder self() {
+                return this;
+            }
+
+            /**
+             * Builds and returns a {@link TextLinkifyEvent}.
+             */
+            @NonNull
+            public TextLinkifyEvent build() {
+                return new TextLinkifyEvent(this);
+            }
+        }
+    }
+
+    /**
+     * This class represents events that are related to the language detection feature.
+     * <p>
+     * <pre>
+     *     // Translate action shown for foreign text.
+     *     new LanguageDetectionEvent.Builder(TYPE_ACTIONS_SHOWN)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(language)
+     *         .setScore(score)
+     *         .setActionIndices(textClassification.getActions().indexOf(translateAction))
+     *         .setEventIndex(0)
+     *         .build();
+     *
+     *     // Translate action selected.
+     *     new LanguageDetectionEvent.Builder(TYPE_SMART_ACTION)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(textClassification.getId())
+     *         .setEntityTypes(language)
+     *         .setScore(score)
+     *         .setActionIndices(textClassification.getActions().indexOf(translateAction))
+     *         .setEventIndex(1)
+     *         .build();
+     */
+    public static final class LanguageDetectionEvent extends TextClassifierEvent
+            implements Parcelable {
+
+        @NonNull
+        public static final Creator<LanguageDetectionEvent> CREATOR =
+                new Creator<LanguageDetectionEvent>() {
+                    @Override
+                    public LanguageDetectionEvent createFromParcel(Parcel in) {
+                        // skip token, we already know this is a LanguageDetectionEvent.
+                        in.readInt();
+                        return new LanguageDetectionEvent(in);
+                    }
+
+                    @Override
+                    public LanguageDetectionEvent[] newArray(int size) {
+                        return new LanguageDetectionEvent[size];
+                    }
+                };
+
+        @Nullable
+        private final ULocale mLocale;
+
+        private LanguageDetectionEvent(Parcel in) {
+            super(in);
+            final String languageTag = in.readString();
+            mLocale = languageTag == null ? null : ULocale.forLanguageTag(languageTag);
+        }
+
+        private LanguageDetectionEvent(LanguageDetectionEvent.Builder builder) {
+            super(builder);
+            mLocale = builder.mLocale;
+        }
+
+        /**
+         * Returns the detected locale.
+         */
+        @Nullable
+        public ULocale getLocale() {
+            return mLocale;
+        }
+
+        /**
+         * Builder class for {@link LanguageDetectionEvent}.
+         */
+        public static final class Builder
+                extends TextClassifierEvent.Builder<LanguageDetectionEvent.Builder> {
+            @Nullable
+            private ULocale mLocale;
+
+            /**
+             * Creates a builder for building {@link TextSelectionEvent}s.
+             *
+             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+             */
+            public Builder(@Type int eventType) {
+                super(TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType);
+            }
+
+            /**
+             * Sets the detected locale.
+             */
+            @NonNull
+            public Builder setLocale(@Nullable ULocale locale) {
+                mLocale = locale;
+                return this;
+            }
+
+            @Override
+            Builder self() {
+                return this;
+            }
+
+            /**
+             * Builds and returns a {@link LanguageDetectionEvent}.
+             */
+            @NonNull
+            public LanguageDetectionEvent build() {
+                return new LanguageDetectionEvent(this);
+            }
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeString(mLocale == null ? null : mLocale.toLanguageTag());
+        }
+    }
+
+    /**
+     * This class represents events that are related to the conversation actions feature.
+     * <p>
+     * <pre>
+     *     // Conversation (contextual) actions/replies generated.
+     *     new ConversationActionsEvent.Builder(TYPE_ACTIONS_GENERATED)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(conversationActions.getId())
+     *         .setEntityTypes(getTypes(conversationActions))
+     *         .setActionIndices(range(conversationActions.getActions().size()))
+     *         .setEventIndex(0)
+     *         .build();
+     *
+     *     // Conversation actions/replies presented to user.
+     *     new ConversationActionsEvent.Builder(TYPE_ACTIONS_SHOWN)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(conversationActions.getId())
+     *         .setEntityTypes(getTypes(conversationActions))
+     *         .setActionIndices(range(conversationActions.getActions().size()))
+     *         .setEventIndex(1)
+     *         .build();
+     *
+     *     // User clicked the "Reply" button to compose their custom reply.
+     *     new ConversationActionsEvent.Builder(TYPE_MANUAL_REPLY)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(conversationActions.getId())
+     *         .setEventIndex(2)
+     *         .build();
+     *
+     *     // User selected a smart (contextual) action/reply.
+     *     new ConversationActionsEvent.Builder(TYPE_SMART_ACTION)
+     *         .setEventContext(classificationContext)
+     *         .setResultId(conversationActions.getId())
+     *         .setEntityTypes(conversationActions.get(1).getType())
+     *         .setScore(conversationAction.get(1).getConfidenceScore())
+     *         .setActionIndices(1)
+     *         .setEventIndex(2)
+     *         .build();
+     * </pre>
+     */
+    public static final class ConversationActionsEvent extends TextClassifierEvent
+            implements Parcelable {
+
+        @NonNull
+        public static final Creator<ConversationActionsEvent> CREATOR =
+                new Creator<ConversationActionsEvent>() {
+                    @Override
+                    public ConversationActionsEvent createFromParcel(Parcel in) {
+                        // skip token, we already know this is a ConversationActionsEvent.
+                        in.readInt();
+                        return new ConversationActionsEvent(in);
+                    }
+
+                    @Override
+                    public ConversationActionsEvent[] newArray(int size) {
+                        return new ConversationActionsEvent[size];
+                    }
+                };
+
+        private ConversationActionsEvent(Parcel in) {
+            super(in);
+        }
+
+        private ConversationActionsEvent(ConversationActionsEvent.Builder builder) {
+            super(builder);
+        }
+
+        /**
+         * Builder class for {@link ConversationActionsEvent}.
+         */
+        public static final class Builder
+                extends TextClassifierEvent.Builder<ConversationActionsEvent.Builder> {
+            /**
+             * Creates a builder for building {@link TextSelectionEvent}s.
+             *
+             * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION}
+             */
+            public Builder(@Type int eventType) {
+                super(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType);
+            }
+
+            @Override
+            Builder self() {
+                return this;
+            }
+
+            /**
+             * Builds and returns a {@link ConversationActionsEvent}.
+             */
+            @NonNull
+            public ConversationActionsEvent build() {
+                return new ConversationActionsEvent(this);
+            }
+        }
     }
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
index 6a12250..3e088b8 100644
--- a/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
+++ b/core/java/android/view/textclassifier/TextClassifierEventTronLogger.java
@@ -65,9 +65,10 @@
         final LogMaker log = new LogMaker(category)
                 .setSubtype(getLogType(event))
                 .addTaggedData(FIELD_TEXT_CLASSIFIER_SESSION_ID, event.getResultId())
-                .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event))
-                .addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScore());
-
+                .addTaggedData(FIELD_TEXTCLASSIFIER_MODEL, getModelName(event));
+        if (event.getScores().length >= 1) {
+            log.addTaggedData(FIELD_TEXT_CLASSIFIER_SCORE, event.getScores()[0]);
+        }
         String[] entityTypes = event.getEntityTypes();
         // The old logger does not support a field of list type, and thus workaround by store them
         // in three separate fields. This is not an issue with the new logger.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 323bf59..3297523 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -307,6 +307,8 @@
             final String detectLanguageTags = detectLanguageTagsFromText(request.getText());
             final AnnotatorModel annotatorImpl =
                     getAnnotatorImpl(request.getDefaultLocales());
+            final boolean isSerializedEntityDataEnabled =
+                    ExtrasUtils.isSerializedEntityDataEnabled(request);
             final AnnotatorModel.AnnotatedSpan[] annotations =
                     annotatorImpl.annotate(
                             textString,
@@ -314,7 +316,10 @@
                                     refTime.toInstant().toEpochMilli(),
                                     refTime.getZone().getId(),
                                     localesString,
-                                    detectLanguageTags));
+                                    detectLanguageTags,
+                                    entitiesToIdentify,
+                                    AnnotatorModel.AnnotationUsecase.SMART.getValue(),
+                                    isSerializedEntityDataEnabled));
             for (AnnotatorModel.AnnotatedSpan span : annotations) {
                 final AnnotatorModel.ClassificationResult[] results =
                         span.getClassification();
@@ -326,7 +331,11 @@
                 for (int i = 0; i < results.length; i++) {
                     entityScores.put(results[i].getCollection(), results[i].getScore());
                 }
-                builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores);
+                Bundle extras = new Bundle();
+                if (isSerializedEntityDataEnabled) {
+                    ExtrasUtils.putEntities(extras, results);
+                }
+                builder.addLink(span.getStartIndex(), span.getEndIndex(), entityScores, extras);
             }
             final TextLinks links = builder.build();
             final long endTimeMs = System.currentTimeMillis();
@@ -451,10 +460,6 @@
         Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
         List<ConversationAction> conversationActions = new ArrayList<>();
         for (ActionsSuggestionsModel.ActionSuggestion nativeSuggestion : nativeSuggestions) {
-            if (request.getMaxSuggestions() >= 0
-                    && conversationActions.size() == request.getMaxSuggestions()) {
-                break;
-            }
             String actionType = nativeSuggestion.getActionType();
             if (!expectedTypes.contains(actionType)) {
                 continue;
@@ -484,6 +489,10 @@
         }
         conversationActions =
                 ActionsSuggestionsHelper.removeActionsWithDuplicates(conversationActions);
+        if (request.getMaxSuggestions() >= 0
+                && conversationActions.size() > request.getMaxSuggestions()) {
+            conversationActions = conversationActions.subList(0, request.getMaxSuggestions());
+        }
         String resultId = ActionsSuggestionsHelper.createResultId(
                 mContext,
                 request.getConversation(),
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 26dba45..137b67c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -413,9 +413,6 @@
         if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
             setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
         }
-        if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
-            setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
-        }
 
         if (context == null) {
             throw new IllegalArgumentException("Invalid context argument");
@@ -2799,11 +2796,6 @@
     }
 
     @Override
-    public void onProvideContentCaptureStructure(ViewStructure structure, int flags) {
-        mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
-    }
-
-    @Override
     public void autofill(SparseArray<AutofillValue>values) {
         mProvider.getViewDelegate().autofill(values);
     }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index c55f7d6..c3bb9a0 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1318,8 +1318,7 @@
             @ViewStructureType int viewFor, int flags) {
         super.onProvideStructure(structure, viewFor, flags);
 
-        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
-                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
             final Adapter adapter = getAdapter();
             if (adapter == null) return;
 
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 564cfdd..51ca805 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -933,12 +933,11 @@
             final String language = ExtrasUtils.getEntityType(foreignLanguageExtra);
             final float score = ExtrasUtils.getScore(foreignLanguageExtra);
             final String model = ExtrasUtils.getModelName(foreignLanguageExtra);
-            return new TextClassifierEvent.Builder(
-                    TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType)
+            return new TextClassifierEvent.LanguageDetectionEvent.Builder(eventType)
                     .setEventContext(classificationContext)
                     .setResultId(classification.getId())
                     .setEntityTypes(language)
-                    .setScore(score)
+                    .setScores(score)
                     .setActionIndices(classification.getActions().indexOf(translateAction))
                     .setModelName(model)
                     .build();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a961783..618b05f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -161,8 +161,6 @@
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
-import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
@@ -978,9 +976,6 @@
         if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
             setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
         }
-        if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
-            setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
-        }
 
         setTextInternal("");
 
@@ -10520,8 +10515,7 @@
     }
 
     /**
-     * Notify managers (such as {@link AutofillManager} and {@link ContentCaptureManager}) that are
-     * interested on text changes.
+     * Notify managers (such as {@link AutofillManager}) that are interested in text changes.
      */
     private void notifyListeningManagersAfterTextChanged() {
 
@@ -10537,22 +10531,6 @@
                 afm.notifyValueChanged(TextView.this);
             }
         }
-
-        // TODO(b/121045053): should use a flag / boolean to keep status of SHOWN / HIDDEN instead
-        // of using isLaidout(), so it's not called in cases where it's laid out but a
-        // notifyAppeared was not sent.
-
-        // ContentCapture
-        if (isLaidOut() && isImportantForContentCapture() && isTextEditable()) {
-            final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
-            if (cm != null && cm.isContentCaptureEnabled()) {
-                final ContentCaptureSession session = getContentCaptureSession();
-                if (session != null) {
-                    // TODO(b/111276913): pass flags when edited by user / add CTS test
-                    session.notifyViewTextChanged(getAutofillId(), getText());
-                }
-            }
-        }
     }
 
     private boolean isAutofillable() {
@@ -11386,8 +11364,7 @@
 
         final boolean isPassword = hasPasswordTransformationMethod()
                 || isPasswordInputType(getInputType());
-        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
-                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
             if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                 structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
             }
@@ -11403,12 +11380,8 @@
             }
         }
 
-        if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
-                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+        if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
             if (mLayout == null) {
-                if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
-                    Log.w(LOG_TAG, "onProvideContentCaptureStructure(): calling assumeLayout()");
-                }
                 assumeLayout();
             }
             Layout layout = mLayout;
@@ -11496,8 +11469,7 @@
                 }
             }
 
-            if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
-                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) {
                 // Extract style information that applies to the TextView as a whole.
                 int style = 0;
                 int typefaceStyle = getTypefaceStyle();
@@ -11525,8 +11497,7 @@
                 structure.setTextStyle(getTextSize(), getCurrentTextColor(),
                         AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
             }
-            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
-                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                 structure.setMinTextEms(getMinEms());
                 structure.setMaxTextEms(getMaxEms());
                 int maxLength = -1;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index b8ac6dc..54338bf 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -84,6 +84,7 @@
 import android.service.chooser.ChooserTargetService;
 import android.service.chooser.IChooserTargetResult;
 import android.service.chooser.IChooserTargetService;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.HashedStringCache;
@@ -1349,13 +1350,13 @@
         appPredictor.notifyAppTargetEvent(
                 new AppTargetEvent.Builder(
                     // TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId.
-                    new AppTarget.Builder(new AppTargetId(shortcutId))
-                        .setTarget(componentName.getPackageName(), getUser())
+                    new AppTarget.Builder(new AppTargetId(shortcutId),
+                            componentName.getPackageName(), getUser())
                         .setClassName(componentName.getClassName())
                         .build(),
-                    AppTargetEvent.ACTION_LAUNCH
-                ).setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
-                .build());
+                    AppTargetEvent.ACTION_LAUNCH)
+                    .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
+                    .build());
     }
 
     @Nullable
@@ -1546,6 +1547,29 @@
         float getModifiedScore();
 
         ChooserTarget getChooserTarget();
+
+        /**
+          * Do not label as 'equals', since this doesn't quite work
+          * as intended with java 8.
+          */
+        default boolean isSimilar(ChooserTargetInfo other) {
+            if (other == null) return false;
+
+            ChooserTarget ct1 = getChooserTarget();
+            ChooserTarget ct2 = other.getChooserTarget();
+
+            // If either is null, there is not enough info to make an informed decision
+            // about equality, so just exit
+            if (ct1 == null || ct2 == null) return false;
+
+            if (ct1.getComponentName().equals(ct2.getComponentName())
+                    && TextUtils.equals(getDisplayLabel(), other.getDisplayLabel())
+                    && TextUtils.equals(getExtendedInfo(), other.getExtendedInfo())) {
+                return true;
+            }
+
+            return false;
+        }
     }
 
     /**
@@ -1624,6 +1648,7 @@
         private final DisplayResolveInfo mSourceInfo;
         private final ResolveInfo mBackupResolveInfo;
         private final ChooserTarget mChooserTarget;
+        private final String mDisplayLabel;
         private Drawable mBadgeIcon = null;
         private CharSequence mBadgeContentDescription;
         private Drawable mDisplayIcon;
@@ -1661,6 +1686,8 @@
 
             mFillInIntent = null;
             mFillInFlags = 0;
+
+            mDisplayLabel = sanitizeDisplayLabel(chooserTarget.getTitle());
         }
 
         private SelectableTargetInfo(SelectableTargetInfo other, Intent fillInIntent, int flags) {
@@ -1673,6 +1700,14 @@
             mFillInIntent = fillInIntent;
             mFillInFlags = flags;
             mModifiedScore = other.mModifiedScore;
+
+            mDisplayLabel = sanitizeDisplayLabel(mChooserTarget.getTitle());
+        }
+
+        private String sanitizeDisplayLabel(CharSequence label) {
+            SpannableStringBuilder sb = new SpannableStringBuilder(label);
+            sb.clearSpans();
+            return sb.toString();
         }
 
         public boolean isSuspended() {
@@ -1811,7 +1846,7 @@
 
         @Override
         public CharSequence getDisplayLabel() {
-            return mChooserTarget.getTitle();
+            return mDisplayLabel;
         }
 
         @Override
@@ -2229,8 +2264,6 @@
             final float baseScore = getBaseScore(origTarget, isShortcutResult);
             Collections.sort(targets, mBaseTargetComparator);
 
-
-
             float lastScore = 0;
             boolean shouldNotify = false;
             for (int i = 0, N = Math.min(targets.size(), MAX_TARGETS_PER_SERVICE); i < N; i++) {
@@ -2305,8 +2338,15 @@
                 return false;
             }
 
-            final float newScore = chooserTargetInfo.getModifiedScore();
+            // Check for duplicates and abort if found
+            for (ChooserTargetInfo otherTargetInfo : mServiceTargets) {
+                if (chooserTargetInfo.isSimilar(otherTargetInfo)) {
+                    return false;
+                }
+            }
+
             int currentSize = mServiceTargets.size();
+            final float newScore = chooserTargetInfo.getModifiedScore();
             for (int i = 0; i < Math.min(currentSize, MAX_SERVICE_TARGETS); i++) {
                 final ChooserTargetInfo serviceTarget = mServiceTargets.get(i);
                 if (serviceTarget == null) {
@@ -2393,15 +2433,11 @@
          * @return true if the view width has changed
          */
         public boolean calculateChooserTargetWidth(int width) {
-            int targetMinWidth = getResources().getDimensionPixelSize(
-                    R.dimen.chooser_target_width);
-
             if (width == 0) {
                 return false;
             }
 
-            int targetWidth =  width / getMaxTargetsPerRow();
-            int newWidth = Math.max(targetWidth, targetMinWidth);
+            int newWidth =  width / getMaxTargetsPerRow();
             if (newWidth != mChooserTargetWidth) {
                 mChooserTargetWidth = newWidth;
                 return true;
@@ -2622,12 +2658,24 @@
             }
         }
 
+        /**
+         * Need to merge CALLER + ranked STANDARD into a single row. All other types
+         * are placed into their own row as determined by their target type, and dividers
+         * are added in the list to separate each type.
+         */
+        int getRowType(int rowPosition) {
+            int positionType = mChooserListAdapter.getPositionTargetType(rowPosition);
+            if (positionType == ChooserListAdapter.TARGET_CALLER) {
+                return ChooserListAdapter.TARGET_STANDARD;
+            }
+
+            return positionType;
+        }
+
         void bindViewHolder(int rowPosition, RowViewHolder holder) {
             final int start = getFirstRowPosition(rowPosition);
-            final int startType = mChooserListAdapter.getPositionTargetType(start);
-
-            final int lastStartType = mChooserListAdapter.getPositionTargetType(
-                    getFirstRowPosition(rowPosition - 1));
+            final int startType = getRowType(start);
+            final int lastStartType = getRowType(getFirstRowPosition(rowPosition - 1));
 
             final ViewGroup row = holder.getViewGroup();
 
@@ -2639,7 +2687,7 @@
 
             int columnCount = holder.getColumnCount();
             int end = start + columnCount - 1;
-            while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) {
+            while (getRowType(end) != startType && end >= start) {
                 end--;
             }
 
@@ -2691,14 +2739,15 @@
                 return row * getMaxTargetsPerRow();
             }
 
-            final int callerCount = mChooserListAdapter.getCallerTargetCount();
-            final int callerRows = (int) Math.ceil((float) callerCount / getMaxTargetsPerRow());
-            if (row < callerRows + serviceRows) {
+            final int callerAndRankedCount = mChooserListAdapter.getCallerTargetCount()
+                                                 + mChooserListAdapter.getRankedTargetCount();
+            final int callerAndRankedRows = getCallerAndRankedTargetRowCount();
+            if (row < callerAndRankedRows + serviceRows) {
                 return serviceCount + (row - serviceRows) * getMaxTargetsPerRow();
             }
 
-            return callerCount + serviceCount
-                    + (row - callerRows - serviceRows) * getMaxTargetsPerRow();
+            return callerAndRankedCount + serviceCount
+                    + (row - callerAndRankedRows - serviceRows) * getMaxTargetsPerRow();
         }
 
         public void handleScroll(View v, int y, int oldy) {
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
index 69d9ccc..b5f2147 100644
--- a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
@@ -31,4 +31,5 @@
             in IMultiClientInputMethodSession multiClientSession, in InputChannel writeChannel);
     void reportImeWindowTarget(int clientId, int targetWindowHandle, in IBinder imeWindowToken);
     boolean isUidAllowedOnDisplay(int displayId, int uid);
+    void setActive(int clientId, boolean active);
 }
diff --git a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
index 9220117..1cf6887 100644
--- a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
@@ -212,4 +212,21 @@
         }
     }
 
+    /**
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#setActive(int, boolean)}.
+     * @param clientId client ID to be set active/inactive
+     * @param active {@code true} set set active.
+     */
+    @AnyThread
+    public void setActive(int clientId, boolean active) {
+        final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setActive(clientId, active);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index fd75f4f..21f8d87 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -45,6 +45,7 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.media.session.MediaController;
@@ -115,6 +116,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Android-specific Window.
@@ -3926,4 +3928,15 @@
     public WindowInsetsController getInsetsController() {
         return mDecor.getWindowInsetsController();
     }
+
+    @Override
+    public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
+        getViewRootImpl().setRootSystemGestureExclusionRects(rects);
+    }
+
+    @Override
+    @NonNull
+    public List<Rect> getSystemGestureExclusionRects() {
+        return getViewRootImpl().getRootSystemGestureExclusionRects();
+    }
 }
diff --git a/core/java/com/android/internal/util/TrafficStatsConstants.java b/core/java/com/android/internal/util/TrafficStatsConstants.java
new file mode 100644
index 0000000..2806ae2
--- /dev/null
+++ b/core/java/com/android/internal/util/TrafficStatsConstants.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.internal.util;
+
+/**
+ * Constants for traffic stats.
+ * @hide
+ */
+public class TrafficStatsConstants {
+    // These tags are used by the network stack to do traffic for its own purposes. Traffic
+    // tagged with these will be counted toward the network stack and must stay inside the
+    // range defined by
+    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_START} and
+    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_END}.
+    public static final int TAG_SYSTEM_DHCP = 0xFFFFFE01;
+    public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFE02;
+    public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFE03;
+
+    public static final int TAG_SYSTEM_NTP = 0xFFFFFF41;
+    public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
+    public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
+
+    // These tags are used by the network stack to do traffic on behalf of apps. Traffic
+    // tagged with these will be counted toward the app on behalf of which the network
+    // stack is doing this traffic. These values must stay inside the range defined by
+    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_START} and
+    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_END}.
+    public static final int TAG_SYSTEM_PROBE = 0xFFFFFF81;
+}
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 19a1c72..1e6d49e 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -18,42 +18,29 @@
 
 #include "core_jni_helpers.h"
 
-void* android::nio_getPointer(JNIEnv *_env, jobject buffer, jarray *array) {
-    assert(array);
+namespace android {
 
-    jint position;
-    jint limit;
-    jint elementSizeShift;
-    jlong pointer = jniGetNioBufferFields(_env, buffer, &position, &limit, &elementSizeShift);
+AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit)
+        : fEnv(env), fCommit(commit) {
+    jlong pointer = jniGetNioBufferPointer(fEnv, nioBuffer);
     if (pointer != 0L) {
-        pointer += position << elementSizeShift;
-        return reinterpret_cast<void*>(pointer);
-    }
-
-    jint offset = jniGetNioBufferBaseArrayOffset(_env, buffer);
-    *array = jniGetNioBufferBaseArray(_env, buffer);
-    void * data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    return reinterpret_cast<void*>(reinterpret_cast<char*>(data) + offset);
-}
-
-
-void android::nio_releasePointer(JNIEnv *_env, jarray array, void *data,
-                                jboolean commit) {
-    _env->ReleasePrimitiveArrayCritical(array, data,
-                                        commit ? 0 : JNI_ABORT);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-android::AutoBufferPointer::AutoBufferPointer(JNIEnv* env, jobject nioBuffer,
-                                              jboolean commit) {
-    fEnv = env;
-    fCommit = commit;
-    fPointer = android::nio_getPointer(env, nioBuffer, &fArray);
-}
-
-android::AutoBufferPointer::~AutoBufferPointer() {
-    if (NULL != fArray) {
-        android::nio_releasePointer(fEnv, fArray, fPointer, fCommit);
+        // Buffer is backed by a direct buffer.
+        fArray = nullptr;
+        fElements = nullptr;
+        fPointer = reinterpret_cast<void*>(pointer);
+    } else {
+        // Buffer is backed by a managed array.
+        jint byteOffset = jniGetNioBufferBaseArrayOffset(fEnv, nioBuffer);
+        fArray = jniGetNioBufferBaseArray(fEnv, nioBuffer);
+        fElements = fEnv->GetPrimitiveArrayCritical(fArray, /* isCopy= */ nullptr);
+        fPointer = reinterpret_cast<void*>(reinterpret_cast<char*>(fElements) + byteOffset);
     }
 }
+
+AutoBufferPointer::~AutoBufferPointer() {
+    if (nullptr != fArray) {
+        fEnv->ReleasePrimitiveArrayCritical(fArray, fElements, fCommit ? 0 : JNI_ABORT);
+    }
+}
+
+}  // namespace android
diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h
index c634cb91..aa75dd0 100644
--- a/core/jni/android_nio_utils.h
+++ b/core/jni/android_nio_utils.h
@@ -20,52 +20,60 @@
 #include <android_runtime/AndroidRuntime.h>
 
 namespace android {
-    
-/**
- * Given an nio.Buffer, return a pointer to it, beginning at its current
- * position. The returned pointer is only valid for the current JNI stack-frame.
- * For performance, it does not create any global references, so the getPointer
- * (and releasePointer if array is returned non-null) must be done in the
- * same JNI stack-frame.
- *
- * @param env   The current JNI env
- * @param buffer    The nio.Buffer object
- * @param array     REQUIRED. Output. If on return it is set to non-null, then
- *                  nio_releasePointer must be called with the array
- *                  and the returned pointer when the caller is through with it.
- *                  If on return it is set to null, do not call
- *                  nio_releasePointer.
- * @return The pointer to the memory in the buffer object
- */
-void* nio_getPointer(JNIEnv *env, jobject buffer, jarray *array);
 
 /**
- * Call this if android_nio_getPointer returned non-null in its array parameter.
- * Pass that array and the returned pointer when you are done accessing the
- * pointer. If called (i.e. array is non-null), it must be called in the same
- * JNI stack-frame as getPointer
+ * Class providing scoped access to the memory backing a java.nio.Buffer instance.
  *
- * @param env   The current JNI env
- * @param buffer    The array returned from android_nio_getPointer (!= null)
- * @param pointer   The pointer returned by android_nio_getPointer
- * @param commit    JNI_FALSE if the pointer was just read, and JNI_TRUE if
- *                  the pointer was written to.
+ * Instances of this class should only be allocated on the stack as heap allocation is not
+ * supported.
+ *
+ * Instances of this class do not create any global references for performance reasons.
  */
-void nio_releasePointer(JNIEnv *env, jarray array, void *pointer,
-                                jboolean commit);
-
-class AutoBufferPointer {
+class AutoBufferPointer final {
 public:
+    /** Constructor for an AutoBufferPointer instance.
+     *
+     * @param env          The current JNI env
+     * @param nioBuffer    Instance of a java.nio.Buffer whose memory will be accessed.
+     * @param commit       JNI_TRUE if the underlying memory will be updated and should be
+     *                     copied back to the managed heap. JNI_FALSE if the data will
+     *                     not be modified or the modifications may be discarded.
+     *
+     * The commit parameter is only applicable if the buffer is backed by a managed heap
+     * array and the runtime had to provide a copy of the data rather than the original data.
+     */
     AutoBufferPointer(JNIEnv* env, jobject nioBuffer, jboolean commit);
+
+    /** Destructor for an AutoBufferPointer instance.
+     *
+     * Releases critical managed heap array pointer if acquired.
+     */
     ~AutoBufferPointer();
 
+    /**
+     * Returns a pointer to the current position of the buffer provided to the constructor.  This
+     * pointer is only valid whilst the AutoBufferPointer instance remains in scope.
+     */
     void* pointer() const { return fPointer; }
 
 private:
-    JNIEnv* fEnv;
-    void*   fPointer;
-    jarray  fArray;
-    jboolean fCommit;
+    JNIEnv* const fEnv;
+    void* fPointer;   // Pointer to current buffer position when constructed.
+    void* fElements;  // Pointer to array element 0 (null if buffer is direct, may be
+                      // within fArray or point to a copy of the array).
+    jarray fArray;    // Pointer to array on managed heap.
+    const jboolean fCommit;  // Flag to commit data to source (when fElements is a copy of fArray).
+
+    // Unsupported constructors and operators.
+    AutoBufferPointer() = delete;
+    AutoBufferPointer(AutoBufferPointer&) = delete;
+    AutoBufferPointer& operator=(AutoBufferPointer&) = delete;
+    static void* operator new(std::size_t);
+    static void* operator new[](std::size_t);
+    static void* operator new(std::size_t, void*);
+    static void* operator new[](std::size_t, void*);
+    static void operator delete(void*, std::size_t);
+    static void operator delete[](void*, std::size_t);
 };
 
 }   /* namespace android */
diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto
index c357065..566861b 100644
--- a/core/proto/android/os/enums.proto
+++ b/core/proto/android/os/enums.proto
@@ -78,6 +78,41 @@
     TEMPERATURE_TYPE_NPU = 9;
 }
 
+// Device throttling severity
+// These constants are defined in hardware/interfaces/thermal/2.0/types.hal.
+// Any change to the types in the thermal hal should be made here as well.
+enum ThrottlingSeverityEnum {
+    // Not under throttling.
+    NONE = 0;
+    // Light throttling where UX is not impacted.
+    LIGHT = 1;
+    // Moderate throttling where UX is not largely impacted.
+    MODERATE = 2;
+    // Severe throttling where UX is largely impacted.
+    // Similar to 1.0 throttlingThreshold.
+    SEVERE = 3;
+    // Platform has done everything to reduce power.
+    CRITICAL = 4;
+    // Key components in platform are shutting down due to thermal condition.
+    // Device functionalities will be limited.
+    EMERGENCY = 5;
+    // Need shutdown immediately.
+    SHUTDOWN = 6;
+};
+
+// Device cooling device types.
+// These constants are defined in hardware/interfaces/thermal/2.0/types.hal.
+// Any change to the types in the thermal hal should be made here as well.
+enum CoolingTypeEnum {
+    FAN = 0;
+    BATTERY = 1;
+    CPU = 2;
+    GPU = 3;
+    MODEM = 4;
+    NPU = 5;
+    COMPONENT = 6;
+};
+
 // Wakelock types, primarily used by android/os/PowerManager.java.
 enum WakeLockLevelEnum {
     // NOTE: Wake lock levels were previously defined as a bit field, except
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index 371bcfe..9fa7c54 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -19,15 +19,16 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">
-    <translate
-        android:fromYDelta="-2%"
-        android:toYDelta="0"
-        android:interpolator="@interpolator/fast_out_slow_in"
-        android:duration="425"/>
-    <alpha
-        android:fromAlpha="0.9"
-        android:toAlpha="1.0"
-        android:interpolator="@interpolator/activity_close_dim"
-        android:startOffset="0"
-        android:duration="425"/>
+    <scale
+        android:fromXScale="1.1"
+        android:toXScale="1"
+        android:fromYScale="1.1"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index d87f100..1599ae8 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -20,25 +20,25 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false"
     android:zAdjustment="top">
-    <translate
-        android:fromYDelta="0"
-        android:toYDelta="4.1%"
-        android:interpolator="@interpolator/fast_out_slow_in"
-        android:duration="425"/>
-    <cliprect
-        android:fromLeft="0%"
-        android:fromTop="0%"
-        android:fromRight="100%"
-        android:fromBottom="100%"
-        android:toLeft="0%"
-        android:toTop="95.9%"
-        android:toRight="100%"
-        android:toBottom="100%"
-        android:interpolator="@interpolator/fast_out_extra_slow_in"
-        android:duration="425"/>
     <alpha
-        android:fromAlpha="1.0"
-        android:toAlpha="1.0"
-        android:interpolator="@interpolator/fast_out_linear_in"
-        android:duration="425"/>
+        android:fromAlpha="1"
+        android:toAlpha="0.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="33"
+        android:duration="50"/>
+    <scale
+        android:fromXScale="1"
+        android:toXScale="0.9"
+        android:fromYScale="1"
+        android:toYScale="0.9"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
 </set>
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index cb03070..38d3e8ed 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -18,20 +18,25 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">
-    <translate
-        android:fromYDelta="4.1%"
-        android:toYDelta="0"
-        android:interpolator="@interpolator/fast_out_slow_in"
-        android:duration="425"/>
-    <cliprect
-        android:fromLeft="0%"
-        android:fromTop="95.9%"
-        android:fromRight="100%"
-        android:fromBottom="100%"
-        android:toLeft="0%"
-        android:toTop="0%"
-        android:toRight="100%"
-        android:toBottom="100%"
+    <alpha
+        android:fromAlpha="0"
+        android:toAlpha="1.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="50"
+        android:duration="50"/>
+    <scale
+        android:fromXScale="0.85"
+        android:toXScale="1"
+        android:fromYScale="0.85"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
         android:interpolator="@interpolator/fast_out_extra_slow_in"
-        android:duration="425"/>
+        android:duration="400"/>
 </set>
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index d52b150..3865d21 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -18,14 +18,28 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:shareInterpolator="false">
-    <translate
-        android:fromYDelta="0"
-        android:toYDelta="-2%"
-        android:interpolator="@interpolator/fast_out_slow_in"
-        android:duration="425"/>
+
+    <!-- Fade out, over a black surface, which simulates a black scrim -->
     <alpha
-        android:fromAlpha="1.0"
-        android:toAlpha="0.9"
+        android:fromAlpha="1"
+        android:toAlpha="0.4"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
         android:interpolator="@interpolator/linear"
-        android:duration="117"/>
+        android:startOffset="83"
+        android:duration="167"/>
+
+    <scale
+        android:fromXScale="1"
+        android:toXScale="1.05"
+        android:fromYScale="1"
+        android:toYScale="1.05"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/drawable/chooser_row_layer_list.xml b/core/res/res/drawable/chooser_row_layer_list.xml
index 0fb26e1..0800815 100644
--- a/core/res/res/drawable/chooser_row_layer_list.xml
+++ b/core/res/res/drawable/chooser_row_layer_list.xml
@@ -17,7 +17,7 @@
 */
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:bottom="-2dp" android:left="-2dp" android:right="-2dp">
+    <item android:bottom="-5dp" android:left="-5dp" android:right="-5dp">
         <shape android:shape="rectangle">
             <stroke android:width="1dp" android:color="@color/chooser_row_divider"/>
         </shape>
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
index 3c9ffdb..f3ca0af 100644
--- a/core/res/res/layout/chooser_grid_preview_text.xml
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -24,9 +24,9 @@
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:paddingBottom="@dimen/chooser_view_spacing"
-    android:background="?attr/colorBackgroundFloating">
+    android:background="?android:attr/colorBackgroundFloating">
 
-  <LinearLayout
+  <RelativeLayout
       android:layout_width="@dimen/chooser_preview_width"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
@@ -35,28 +35,51 @@
       android:paddingRight="@dimen/chooser_edge_margin_normal"
       android:layout_marginBottom="@dimen/chooser_view_spacing"
       android:id="@+id/content_preview_text_layout">
+
     <TextView
         android:id="@+id/content_preview_text"
-        android:layout_width="0dp"
-        android:layout_weight="1"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
+        android:layout_alignParentStart="true"
+        android:layout_toStartOf="@id/copy_button"
+        android:layout_centerVertical="true"
         android:ellipsize="end"
-        android:gravity="start|top"
-        android:paddingRight="@dimen/chooser_view_spacing"
+        android:textColor="?android:attr/textColorPrimary"
         android:maxLines="2"/>
-    <ImageButton
+
+    <LinearLayout
         android:id="@+id/copy_button"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:padding="12dp"
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:layout_alignParentEnd="true"
+        android:layout_marginStart="@dimen/chooser_view_spacing"
         android:gravity="center"
-        android:layout_gravity="center_vertical"
-        android:src="@drawable/ic_content_copy_gm2"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
         android:clickable="true"
-        android:contentDescription="@string/copy"
-        android:background="?attr/selectableItemBackgroundBorderless"/>
-  </LinearLayout>
+        android:background="?android:attr/selectableItemBackgroundBorderless">
+
+      <ImageView
+          android:layout_width="24dp"
+          android:layout_height="24dp"
+          android:gravity="top|center_horizontal"
+          android:src="@drawable/ic_content_copy_gm2" />
+
+      <TextView
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_marginTop="4dp"
+          android:gravity="center_horizontal"
+          android:text="@string/copy"
+          android:textColor="?android:textColorSecondary"
+          android:textSize="12sp"
+          android:maxWidth="72dp"
+          android:maxLines="2"
+          android:ellipsize="end" />
+    </LinearLayout>
+  </RelativeLayout>
 
   <!-- Required sub-layout so we can get the nice rounded corners-->
   <!-- around this section -->
@@ -89,7 +112,8 @@
         android:layout_gravity="center_vertical"
         android:ellipsize="end"
         android:maxLines="2"
-        android:textSize="20sp"/>
+        android:textSize="20sp"
+        android:textColor="?android:attr/textColorPrimary"/>
   </LinearLayout>
 </LinearLayout>
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ed8f2c1..ab9a298 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2485,24 +2485,7 @@
             <flag name="noExcludeDescendants" value="0x8" />
         </attr>
 
-        <!-- Hints the Android System whether the view node associated with this View should be
-             use for content capture purposes. -->
-        <attr name="importantForContentCapture">
-            <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
-            <flag name="auto" value="0" />
-            <!-- Hint the Android System that this view is important for content capture,
-                  and its children (if any) will be traversed.. -->
-            <flag name="yes" value="0x1" />
-            <!-- Hint the Android System that this view is *not* important for content capture,
-                  but its children (if any) will be traversed.. -->
-            <flag name="no" value="0x2" />
-            <!-- Hint the Android System that this view is important for content capture,
-                 but its children (if any) will not be traversed. -->
-            <flag name="yesExcludeDescendants" value="0x4" />
-            <!-- Hint the Android System that this view is *not* important for content capture,
-                 and its children (if any) will not be traversed. -->
-            <flag name="noExcludeDescendants" value="0x8" />
-        </attr>
+        <attr name="__removed6" />
 
         <!-- Boolean that controls whether a view can take focus while in touch mode.
              If this is true for a view, that view can gain focus when clicked on, and can keep
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5268189..4d6fda9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3483,6 +3483,12 @@
         <item>com.android.messaging</item>
     </string-array>
 
+    <!-- An array of packages that can make sound on the ringer stream in priority-only DND
+     mode -->
+    <string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
+        <item>com.android.dialer</item>
+    </string-array>
+
     <!-- An array of packages which can listen for notifications on low ram devices. -->
     <string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9a8c754..b7d61c8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2922,7 +2922,7 @@
         <public name="settingsSliceUri" />
         <public name="shell" />
         <public name="interactiveUiTimeout" />
-        <public name="importantForContentCapture" />
+        <public name="__removed6" />
         <public name="supportsMultipleDisplays" />
         <public name="useAppZygote" />
         <public name="__removed1" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 94b5da6b..924b036 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3188,6 +3188,7 @@
   <java-symbol type="array" name="config_convert_to_emergency_number_map" />
 
   <java-symbol type="array" name="config_nonBlockableNotificationPackages" />
+  <java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
 
   <java-symbol type="array" name="config_allowedManagedServicesOnLowRamDevices" />
 
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9cb3489..711eaa7 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -38,6 +38,7 @@
 import android.os.IBinder;
 import android.util.MergedConfiguration;
 import android.view.Display;
+import android.view.View;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -153,6 +154,34 @@
     }
 
     @Test
+    public void testHandleActivity_assetsChanged() {
+        final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+        final IBinder[] token = new IBinder[1];
+        final View[] decorView = new View[1];
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            final ActivityThread activityThread = activity.getActivityThread();
+
+            token[0] = activity.getActivityToken();
+            decorView[0] = activity.getWindow().getDecorView();
+
+            // Relaunches all activities
+            activityThread.handleApplicationInfoChanged(activity.getApplicationInfo());
+        });
+
+        final View[] newDecorView = new View[1];
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            final ActivityThread activityThread = activity.getActivityThread();
+
+            final Activity newActivity = activityThread.getActivity(token[0]);
+            newDecorView[0] = activity.getWindow().getDecorView();
+        });
+
+        assertEquals("Window must be preserved", decorView[0], newDecorView[0]);
+    }
+
+    @Test
     public void testHandleActivityConfigurationChanged_DropStaleConfigurations() {
         final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
 
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index d2a1dd9..2280cf1 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -22,6 +22,10 @@
 
 import junit.framework.TestCase;
 
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
 public class BitmapTest extends TestCase {
 
     @SmallTest
@@ -262,4 +266,231 @@
         assertFalse(hardwareBitmap.isMutable());
         assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), hardwareBitmap.getColorSpace());
     }
+
+    @SmallTest
+    public void testCopyWithDirectByteBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to direct buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final byte padValue = 0x5a;
+        final int bytesPerElement = 1;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
+
+        // Write padding
+        directBuffer.put(0, padValue);
+        directBuffer.put(directBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        directBuffer.position(pad);
+        bm1.copyPixelsToBuffer(directBuffer);
+        assertEquals(directBuffer.position(),
+                     pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(directBuffer.get(0), padValue);
+        assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+        // Create bitmap from direct buffer and check match.
+        directBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(directBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
+
+    @SmallTest
+    public void testCopyWithDirectShortBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final short padValue = 0x55aa;
+        final int bytesPerElement = 2;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        ShortBuffer directBuffer =
+                ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asShortBuffer();
+
+        // Write padding
+        directBuffer.put(0, padValue);
+        directBuffer.put(directBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        directBuffer.position(pad);
+        bm1.copyPixelsToBuffer(directBuffer);
+        assertEquals(directBuffer.position(),
+                     pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(directBuffer.get(0), padValue);
+        assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+        // Create bitmap from heap buffer and check match.
+        directBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(directBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
+
+    @SmallTest
+    public void testCopyWithDirectIntBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final int padValue = 0x55aa5a5a;
+        final int bytesPerElement = 4;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        IntBuffer directBuffer =
+                ByteBuffer.allocateDirect(bufferSize * bytesPerElement).asIntBuffer();
+
+        // Write padding
+        directBuffer.put(0, padValue);
+        directBuffer.put(directBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        directBuffer.position(pad);
+        bm1.copyPixelsToBuffer(directBuffer);
+        assertEquals(directBuffer.position(),
+                     pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(directBuffer.get(0), padValue);
+        assertEquals(directBuffer.get(directBuffer.limit() - 1), padValue);
+
+        // Create bitmap from heap buffer and check match.
+        directBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(directBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
+
+    @SmallTest
+    public void testCopyWithHeapByteBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final byte padValue = 0x5a;
+        final int bytesPerElement = 1;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        ByteBuffer heapBuffer = ByteBuffer.allocate(bufferSize);
+
+        // Write padding
+        heapBuffer.put(0, padValue);
+        heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        heapBuffer.position(pad);
+        bm1.copyPixelsToBuffer(heapBuffer);
+        assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(heapBuffer.get(0), padValue);
+        assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+        // Create bitmap from heap buffer and check match.
+        heapBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(heapBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
+
+    @SmallTest
+    public void testCopyWithHeapShortBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final short padValue = 0x55aa;
+        final int bytesPerElement = 2;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        ShortBuffer heapBuffer = ShortBuffer.allocate(bufferSize);
+
+        // Write padding
+        heapBuffer.put(0, padValue);
+        heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        heapBuffer.position(pad);
+        bm1.copyPixelsToBuffer(heapBuffer);
+        assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(heapBuffer.get(0), padValue);
+        assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+        // Create bitmap from heap buffer and check match.
+        heapBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(heapBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
+
+    @SmallTest
+    public void testCopyWithHeapIntBuffer() {
+        // Initialize Bitmap
+        final int width = 2;
+        final int height = 2;
+        final int bytesPerPixel = 2;
+        Bitmap bm1 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm1.setPixels(new int[] { 0xff, 0xeeee, 0xdddddd, 0xcccccccc }, 0, 2, 0, 0, 2, 2);
+
+        // Copy bytes to heap buffer, buffer is padded by fixed amount (pad bytes) either side
+        // of bitmap.
+        final int pad = 1;
+        final int padValue = 0x55aa5a5a;
+        final int bytesPerElement = 4;
+        final int bufferSize = pad + width * height * bytesPerPixel / bytesPerElement + pad;
+        IntBuffer heapBuffer = IntBuffer.allocate(bufferSize);
+
+        // Write padding
+        heapBuffer.put(0, padValue);
+        heapBuffer.put(heapBuffer.limit() - 1, padValue);
+
+        // Copy bitmap
+        heapBuffer.position(pad);
+        bm1.copyPixelsToBuffer(heapBuffer);
+        assertEquals(heapBuffer.position(), pad + width * height * bytesPerPixel / bytesPerElement);
+
+        // Check padding
+        assertEquals(heapBuffer.get(0), padValue);
+        assertEquals(heapBuffer.get(heapBuffer.limit() - 1), padValue);
+
+        // Create bitmap from heap buffer and check match.
+        heapBuffer.position(pad);
+        Bitmap bm2 = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+        bm2.copyPixelsFromBuffer(heapBuffer);
+        assertTrue(bm2.sameAs(bm1));
+    }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index fafd833..0e94abc0 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -709,7 +709,9 @@
                  Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
                  Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS,
                  Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS,
-                 Settings.Secure.BIOMETRIC_DEBUG_ENABLED);
+                 Settings.Secure.BIOMETRIC_DEBUG_ENABLED,
+                 Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+                 Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED);
 
     @Test
     public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index ebbbdec..bdd3038 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -39,11 +39,13 @@
 import android.util.SparseArray;
 import android.view.SurfaceControl.Transaction;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.test.InsetsModeSession;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -62,7 +64,6 @@
  * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
  */
 @Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
 @RunWith(AndroidJUnit4.class)
 public class InsetsAnimationControlImplTest {
 
@@ -72,15 +73,25 @@
     private SurfaceControl mTopLeash;
     private SurfaceControl mNavLeash;
     private InsetsState mInsetsState;
+    private static InsetsModeSession sInsetsModeSession;
 
     @Mock Transaction mMockTransaction;
     @Mock InsetsController mMockController;
     @Mock WindowInsetsAnimationControlListener mMockListener;
     @Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier;
 
+    @BeforeClass
+    public static void setupOnce() {
+        sInsetsModeSession = new InsetsModeSession(NEW_INSETS_MODE_FULL);
+    }
+
+    @AfterClass
+    public static void tearDownOnce() throws Exception {
+        sInsetsModeSession.close();
+    }
+
     @Before
     public void setup() {
-        ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
         MockitoAnnotations.initMocks(this);
         mTopLeash = new SurfaceControl.Builder(mSession)
                 .setName("testSurface")
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 4d8d3f6..1e55828 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -43,7 +43,6 @@
 import android.widget.TextView;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -63,7 +62,6 @@
  * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
  */
 @Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
 @RunWith(AndroidJUnit4.class)
 public class InsetsControllerTest {
 
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index a32fa77..971e143 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -34,7 +34,6 @@
 import android.widget.TextView;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -53,7 +52,6 @@
  * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
  */
 @Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
 @RunWith(AndroidJUnit4.class)
 public class InsetsSourceConsumerTest {
 
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index b55a9c6..533a58e 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -24,7 +24,6 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
@@ -41,7 +40,6 @@
  * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
  */
 @Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
 @RunWith(AndroidJUnit4.class)
 public class InsetsSourceTest {
 
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 8e167da..a73269a 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -40,7 +40,6 @@
 import android.view.WindowInsets.Type;
 import android.view.test.InsetsModeSession;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
@@ -56,7 +55,6 @@
  * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
  */
 @Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
 @RunWith(AndroidJUnit4.class)
 public class InsetsStateTest {
 
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index cd885e0..7c255c9 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -47,6 +47,6 @@
 
     @Test
     public void testRemoveUserData_invalid() {
-        assertThrows(NullPointerException.class, () -> mManager.removeUserData(null));
+        assertThrows(NullPointerException.class, () -> mManager.removeData(null));
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 433991e..aeb8949 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -362,6 +362,38 @@
     }
 
     @Test
+    public void testGenerateLinks_entityData() {
+        if (isTextClassifierDisabled()) return;
+        String text = "The number is +12122537077.";
+        Bundle extras = new Bundle();
+        ExtrasUtils.putIsSerializedEntityDataEnabled(extras, true);
+        TextLinks.Request request = new TextLinks.Request.Builder(text).setExtras(extras).build();
+
+        TextLinks textLinks = mClassifier.generateLinks(request);
+
+        Truth.assertThat(textLinks.getLinks()).hasSize(1);
+        TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+        List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+        Truth.assertThat(entities).hasSize(1);
+        Bundle entity = entities.get(0);
+        Truth.assertThat(ExtrasUtils.getEntityType(entity)).isEqualTo(TextClassifier.TYPE_PHONE);
+    }
+
+    @Test
+    public void testGenerateLinks_entityData_disabled() {
+        if (isTextClassifierDisabled()) return;
+        String text = "The number is +12122537077.";
+        TextLinks.Request request = new TextLinks.Request.Builder(text).build();
+
+        TextLinks textLinks = mClassifier.generateLinks(request);
+
+        Truth.assertThat(textLinks.getLinks()).hasSize(1);
+        TextLinks.TextLink textLink = textLinks.getLinks().iterator().next();
+        List<Bundle> entities = ExtrasUtils.getEntities(textLink.getExtras());
+        Truth.assertThat(entities).isNull();
+    }
+
+    @Test
     public void testDetectLanguage() {
         if (isTextClassifierDisabled()) return;
         String text = "This is English text";
@@ -380,7 +412,7 @@
     }
 
     @Test
-    public void testSuggestConversationActions_textReplyOnly_maxThree() {
+    public void testSuggestConversationActions_textReplyOnly_maxOne() {
         if (isTextClassifierDisabled()) return;
         ConversationActions.Message message =
                 new ConversationActions.Message.Builder(
@@ -399,12 +431,11 @@
                         .build();
 
         ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
-        assertTrue(conversationActions.getConversationActions().size() > 0);
-        for (ConversationAction conversationAction :
-                conversationActions.getConversationActions()) {
-            assertThat(conversationAction,
-                    isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
-        }
+        Truth.assertThat(conversationActions.getConversationActions()).hasSize(1);
+        ConversationAction conversationAction = conversationActions.getConversationActions().get(0);
+        Truth.assertThat(conversationAction.getType()).isEqualTo(
+                ConversationAction.TYPE_TEXT_REPLY);
+        Truth.assertThat(conversationAction.getTextReply()).isNotNull();
     }
 
     @Test
@@ -493,6 +524,24 @@
                 ExtrasUtils.getSerializedEntityData(conversationAction.getExtras())).isNotEmpty();
     }
 
+    @Test
+    public void testSuggetsConversationActions_deduplicate() {
+        if (isTextClassifierDisabled()) return;
+        ConversationActions.Message message =
+                new ConversationActions.Message.Builder(
+                        ConversationActions.Message.PERSON_USER_OTHERS)
+                        .setText("a@android.com b@android.com")
+                        .build();
+        ConversationActions.Request request =
+                new ConversationActions.Request.Builder(Collections.singletonList(message))
+                        .setMaxSuggestions(3)
+                        .build();
+
+        ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+
+        Truth.assertThat(conversationActions.getConversationActions()).isEmpty();
+    }
+
     private boolean isTextClassifierDisabled() {
         return mClassifier == null || mClassifier == TextClassifier.NO_OP;
     }
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 1980a60..2c540e5 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -49,8 +49,6 @@
 public class TextClassifierEventTronLoggerTest {
     private static final String WIDGET_TYPE = "notification";
     private static final String PACKAGE_NAME = "pkg";
-    private static final long EVENT_TIME = System.currentTimeMillis();
-
 
     @Mock
     private MetricsLogger mMetricsLogger;
@@ -68,13 +66,11 @@
         TextClassificationContext textClassificationContext =
                 new TextClassificationContext.Builder(PACKAGE_NAME, WIDGET_TYPE)
                         .build();
-        TextClassifierEvent textClassifierEvent =
-                new TextClassifierEvent.Builder(
-                        TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS,
+        TextClassifierEvent.ConversationActionsEvent textClassifierEvent =
+                new TextClassifierEvent.ConversationActionsEvent.Builder(
                         TextClassifierEvent.TYPE_SMART_ACTION)
                         .setEntityTypes(ConversationAction.TYPE_CALL_PHONE)
-                        .setScore(0.5f)
-                        .setEventTime(EVENT_TIME)
+                        .setScores(0.5f)
                         .setEventContext(textClassificationContext)
                         .build();
 
@@ -83,10 +79,8 @@
         ArgumentCaptor<LogMaker> captor = ArgumentCaptor.forClass(LogMaker.class);
         Mockito.verify(mMetricsLogger).write(captor.capture());
         LogMaker logMaker = captor.getValue();
-        assertThat(logMaker.getCategory()).isEqualTo(
-                CONVERSATION_ACTIONS);
-        assertThat(logMaker.getSubtype()).isEqualTo(
-                ACTION_TEXT_SELECTION_SMART_SHARE);
+        assertThat(logMaker.getCategory()).isEqualTo(CONVERSATION_ACTIONS);
+        assertThat(logMaker.getSubtype()).isEqualTo(ACTION_TEXT_SELECTION_SMART_SHARE);
         assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_FIRST_ENTITY_TYPE))
                 .isEqualTo(ConversationAction.TYPE_CALL_PHONE);
         assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
@@ -101,9 +95,8 @@
 
     @Test
     public void testWriteEvent_unsupportedCategory() {
-        TextClassifierEvent textClassifierEvent =
-                new TextClassifierEvent.Builder(
-                        TextClassifierEvent.CATEGORY_SELECTION,
+        TextClassifierEvent.TextSelectionEvent textClassifierEvent =
+                new TextClassifierEvent.TextSelectionEvent.Builder(
                         TextClassifierEvent.TYPE_SMART_ACTION)
                         .build();
 
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
new file mode 100644
index 0000000..ae3ff86
--- /dev/null
+++ b/core/tests/mockingcoretests/Android.bp
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+
+android_test {
+    name: "FrameworksMockingCoreTests",
+
+    srcs: [
+        "src/**/*.java",
+    ],
+
+    static_libs: [
+        "frameworks-base-testutils",
+        "services.core",
+        "androidx.test.runner",
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "mockito-target-extended-minus-junit4",
+        "platform-test-annotations",
+        "truth-prebuilt",
+        "testables",
+        "ub-uiautomator",
+    ],
+
+    libs: [
+        "android.test.base",
+        "android.test.mock",
+        "android.test.runner",
+    ],
+
+    // These are not normally accessible from apps so they must be explicitly included.
+    jni_libs: [
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
+
+    platform_apis: true,
+    test_suites: ["device-tests"],
+
+    certificate: "platform",
+}
diff --git a/core/tests/mockingcoretests/AndroidManifest.xml b/core/tests/mockingcoretests/AndroidManifest.xml
new file mode 100644
index 0000000..b9ee085
--- /dev/null
+++ b/core/tests/mockingcoretests/AndroidManifest.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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          android:installLocation="internalOnly"
+          package="com.android.frameworks.mockingcoretests"
+          android:sharedUserId="com.android.uid.test">
+
+    <application android:supportsRtl="true" android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.app.activity.ActivityThreadClientTest$TestActivity"
+            android:exported="true">
+        </activity>
+
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.frameworks.mockingcoretests"
+            android:label="Frameworks Mocking Core Tests" />
+</manifest>
diff --git a/core/tests/mockingcoretests/AndroidTest.xml b/core/tests/mockingcoretests/AndroidTest.xml
new file mode 100644
index 0000000..47aa410
--- /dev/null
+++ b/core/tests/mockingcoretests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?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
+  -->
+<configuration description="Runs Frameworks Mocking Core Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="FrameworksMockingCoreTests.apk" />
+    </target_preparer>
+    <option name="test-tag" value="FrameworksMockingCoreTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.frameworks.mockingcoretests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/core/tests/mockingcoretests/README b/core/tests/mockingcoretests/README
new file mode 100644
index 0000000..c0f65c2
--- /dev/null
+++ b/core/tests/mockingcoretests/README
@@ -0,0 +1,33 @@
+* 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.
+
+
+INTRODUCTION
+
+The Android platform core tests that require additional mocking capabilities and use Extended
+Mockito, such as the ability to stub static methods. ExtendedMockito is not fully compatible with
+regular Mockito library, so tests that use it have to be verified and adapted. For that reason a
+separate module is used instead of adding to FrameworksCoreTests.
+
+For more information about ExtendedMockito see documentation of
+com.android.dx.mockito.inline.extended.ExtendedMockito class.
+
+See ../coretests/README for more information on FrameworksCoreTests.
+
+
+INSTRUCTIONS
+
+To build, install and run:
+
+  atest FrameworksMockingCoreTests
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
new file mode 100644
index 0000000..86d55ea
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -0,0 +1,362 @@
+/*
+ * 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.app.activity;
+
+import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
+import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.ActivityThread.ActivityClientRecord;
+import android.app.IActivityTaskManager;
+import android.app.servertransaction.PendingTransactionActions;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.view.WindowManagerGlobal;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+/**
+ * Test for verifying {@link android.app.ActivityThread} class.
+ *
+ * <p>Build/Install/Run:
+ *  atest FrameworksMockingCoreTests:android.app.activity.ActivityThreadClientTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ActivityThreadClientTest {
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnCreate() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            clientSession.launchActivity(r);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnCreate_Finished() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            Activity activity = clientSession.launchActivity(r);
+            activity.finish();
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnStart() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_START, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnStart_Finished() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            Activity activity = clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            activity.finish();
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_START, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnResume() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            clientSession.resumeActivity(r);
+            assertEquals(ON_RESUME, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_START, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnPause() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            clientSession.resumeActivity(r);
+            clientSession.pauseActivity(r);
+            assertEquals(ON_PAUSE, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_START, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testWindowVisibilityChange_OnStop() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            clientSession.resumeActivity(r);
+            clientSession.pauseActivity(r);
+            clientSession.stopActivity(r);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, true);
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.changeVisibility(r, false);
+            assertEquals(ON_STOP, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testLifecycleAfterFinished_OnCreate() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            Activity activity = clientSession.launchActivity(r);
+            activity.finish();
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.startActivity(r);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.resumeActivity(r);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.pauseActivity(r);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.stopActivity(r);
+            assertEquals(ON_CREATE, r.getLifecycleState());
+
+            clientSession.destroyActivity(r);
+            assertEquals(ON_DESTROY, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testLifecycleAfterFinished_OnStart() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            Activity activity = clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            activity.finish();
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.resumeActivity(r);
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.pauseActivity(r);
+            assertEquals(ON_START, r.getLifecycleState());
+
+            clientSession.stopActivity(r);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.destroyActivity(r);
+            assertEquals(ON_DESTROY, r.getLifecycleState());
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void testLifecycleAfterFinished_OnResume() throws Exception {
+        try (ClientMockSession clientSession = new ClientMockSession()) {
+            ActivityClientRecord r = clientSession.stubActivityRecord();
+
+            Activity activity = clientSession.launchActivity(r);
+            clientSession.startActivity(r);
+            clientSession.resumeActivity(r);
+            activity.finish();
+            assertEquals(ON_RESUME, r.getLifecycleState());
+
+            clientSession.pauseActivity(r);
+            assertEquals(ON_PAUSE, r.getLifecycleState());
+
+            clientSession.stopActivity(r);
+            assertEquals(ON_STOP, r.getLifecycleState());
+
+            clientSession.destroyActivity(r);
+            assertEquals(ON_DESTROY, r.getLifecycleState());
+        }
+    }
+
+    private class ClientMockSession implements AutoCloseable {
+        private MockitoSession mMockSession;
+        private ActivityThread mThread;
+
+        private ClientMockSession() throws RemoteException {
+            mThread = ActivityThread.currentActivityThread();
+            mMockSession = mockitoSession()
+                    .strictness(Strictness.LENIENT)
+                    .spyStatic(ActivityTaskManager.class)
+                    .spyStatic(WindowManagerGlobal.class)
+                    .startMocking();
+            doReturn(Mockito.mock(WindowManagerGlobal.class))
+                    .when(WindowManagerGlobal::getInstance);
+            IActivityTaskManager mockAtm = Mockito.mock(IActivityTaskManager.class);
+            doReturn(mockAtm).when(ActivityTaskManager::getService);
+            when(mockAtm.finishActivity(any(), anyInt(), any(), anyInt())).thenReturn(true);
+        }
+
+        private Activity launchActivity(ActivityClientRecord r) {
+            return mThread.handleLaunchActivity(r, null /* pendingActions */,
+                    null /* customIntent */);
+        }
+
+        private void startActivity(ActivityClientRecord r) {
+            mThread.handleStartActivity(r, null /* pendingActions */);
+        }
+
+        private void resumeActivity(ActivityClientRecord r) {
+            mThread.handleResumeActivity(r.token, true /* finalStateRequest */,
+                    true /* isForward */, "test");
+        }
+
+        private void pauseActivity(ActivityClientRecord r) {
+            mThread.handlePauseActivity(r.token, false /* finished */,
+                    false /* userLeaving */, 0 /* configChanges */, null /* pendingActions */,
+                    "test");
+        }
+
+        private void stopActivity(ActivityClientRecord r) {
+            mThread.handleStopActivity(r.token, false /* show */, 0 /* configChanges */,
+                    new PendingTransactionActions(), false /* finalStateRequest */, "test");
+        }
+
+        private void destroyActivity(ActivityClientRecord r) {
+            mThread.handleDestroyActivity(r.token, true /* finishing */, 0 /* configChanges */,
+                    false /* getNonConfigInstance */, "test");
+        }
+
+        private void changeVisibility(ActivityClientRecord r, boolean show) {
+            mThread.handleWindowVisibility(r.token, show);
+        }
+
+        private ActivityClientRecord stubActivityRecord() {
+            ComponentName component = new ComponentName(
+                    InstrumentationRegistry.getInstrumentation().getContext(), TestActivity.class);
+            ActivityInfo info = new ActivityInfo();
+            info.packageName = component.getPackageName();
+            info.name = component.getClassName();
+            info.exported = true;
+            info.applicationInfo = new ApplicationInfo();
+            info.applicationInfo.packageName = info.packageName;
+            info.applicationInfo.uid = UserHandle.myUserId();
+
+            return new ActivityClientRecord(new Binder(), Intent.makeMainActivity(component),
+                    0 /* ident */, info, new Configuration(),
+                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null /* referrer */,
+                    null /* voiceInteractor */, null /* state */, null /* persistentState */,
+                    null /* pendingResults */, null /* pendingNewIntents */, true /* isForward */,
+                    null /* profilerInfo */,  mThread /* client */);
+        }
+
+        @Override
+        public void close() {
+            mMockSession.finishMocking();
+        }
+    }
+
+    // Test activity
+    public static class TestActivity extends Activity {
+    }
+}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 11e4cb8..2ad2e76 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3510,6 +3510,7 @@
     ResStringPool                   keyStrings;
 
     size_t                          typeIdOffset;
+    bool                            definesOverlayable = false;
 };
 
 // A group of objects describing a particular resource package.
@@ -6861,6 +6862,10 @@
                 ALOGW("Found multiple library tables, ignoring...");
             }
         } else {
+            if (ctype == RES_TABLE_OVERLAYABLE_TYPE) {
+                package->definesOverlayable = true;
+            }
+
             status_t err = validate_chunk(chunk, sizeof(ResChunk_header),
                                           endPos, "ResTable_package:unknown");
             if (err != NO_ERROR) {
@@ -7138,6 +7143,11 @@
         return UNKNOWN_ERROR;
     }
 
+    // Idmap is not aware of overlayable, exit since policy checks can't be done
+    if (targetResTable.mPackageGroups[0]->packages[0]->definesOverlayable) {
+        return UNKNOWN_ERROR;
+    }
+
     const ResTable_package* targetPackageStruct =
         targetResTable.mPackageGroups[0]->packages[0]->package;
     const size_t tmpNameSize = arraysize(targetPackageStruct->name);
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
index cdad20e..dc53dd6 100644
--- a/libs/hwui/TreeInfo.cpp
+++ b/libs/hwui/TreeInfo.cpp
@@ -25,6 +25,7 @@
         , prepareTextures(mode == MODE_FULL)
         , canvasContext(canvasContext)
         , damageGenerationId(canvasContext.getFrameNumber())
-        , disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
+        , disableForceDark(canvasContext.useForceDark() ? 0 : 1)
+        , screenSize(canvasContext.getNextFrameSize()) {}
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 04eabac..7e8d12f 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -20,6 +20,7 @@
 #include "utils/Macros.h"
 
 #include <utils/Timers.h>
+#include "SkSize.h"
 
 #include <string>
 
@@ -96,6 +97,8 @@
 
     int disableForceDark;
 
+    const SkISize screenSize;
+
     struct Out {
         bool hasFunctors = false;
         // This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index da905cf..5418b33 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -547,6 +547,11 @@
 }
 
 void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
+    if (canvas->quickReject(bounds)) {
+        // The RenderNode is on screen, but the AVD is not.
+        return;
+    }
+
     // Update the paint for any animatable properties
     SkPaint paint = inPaint;
     paint.setAlpha(mProperties.getRootAlpha() * 255);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 29d5ef2..41bcfc2 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -22,6 +22,7 @@
 #include "renderthread/CanvasContext.h"
 
 #include <SkImagePriv.h>
+#include <SkPathOps.h>
 
 namespace android {
 namespace uirenderer {
@@ -35,7 +36,7 @@
         animatedImage->syncProperties();
     }
     for (auto& vectorDrawable : mVectorDrawables) {
-        vectorDrawable->syncProperties();
+        vectorDrawable.first->syncProperties();
     }
 }
 
@@ -51,6 +52,29 @@
     }
 }
 
+static bool intersects(const SkISize screenSize, const Matrix4& mat, const SkRect& bounds) {
+    Vector3 points[] = { Vector3 {bounds.fLeft, bounds.fTop, 0},
+                         Vector3 {bounds.fRight, bounds.fTop, 0},
+                         Vector3 {bounds.fRight, bounds.fBottom, 0},
+                         Vector3 {bounds.fLeft, bounds.fBottom, 0}};
+    float minX, minY, maxX, maxY;
+    bool first = true;
+    for (auto& point : points) {
+        mat.mapPoint3d(point);
+        if (first) {
+            minX = maxX = point.x;
+            minY = maxY = point.y;
+            first = false;
+        } else {
+            minX = std::min(minX, point.x);
+            minY = std::min(minY, point.y);
+            maxX = std::max(maxX, point.x);
+            maxY = std::max(maxY, point.y);
+        }
+    }
+    return SkRect::Make(screenSize).intersects(SkRect::MakeLTRB(minX, minY, maxX, maxY));
+}
+
 bool SkiaDisplayList::prepareListAndChildren(
         TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
         std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
@@ -107,15 +131,23 @@
         }
     }
 
-    for (auto& vectorDrawable : mVectorDrawables) {
+    for (auto& vectorDrawablePair : mVectorDrawables) {
         // If any vector drawable in the display list needs update, damage the node.
+        auto& vectorDrawable = vectorDrawablePair.first;
         if (vectorDrawable->isDirty()) {
-            isDirty = true;
-            static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
-                    ->getVectorDrawables()
-                    ->push_back(vectorDrawable);
+            Matrix4 totalMatrix;
+            info.damageAccumulator->computeCurrentTransform(&totalMatrix);
+            Matrix4 canvasMatrix(vectorDrawablePair.second);
+            totalMatrix.multiply(canvasMatrix);
+            const SkRect& bounds = vectorDrawable->properties().getBounds();
+            if (intersects(info.screenSize, totalMatrix, bounds)) {
+                isDirty = true;
+                static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
+                        ->getVectorDrawables()
+                        ->push_back(vectorDrawable);
+                vectorDrawable->setPropertyChangeWillBeConsumed(true);
+            }
         }
-        vectorDrawable->setPropertyChangeWillBeConsumed(true);
     }
     return isDirty;
 }
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 3219ad1..b791037 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -22,6 +22,7 @@
 #include "TreeInfo.h"
 #include "hwui/AnimatedImageDrawable.h"
 #include "utils/LinearAllocator.h"
+#include "utils/Pair.h"
 
 #include <deque>
 
@@ -41,12 +42,6 @@
 
 namespace skiapipeline {
 
-/**
- * This class is intended to be self contained, but still subclasses from
- * DisplayList to make it easier to support switching between the two at
- * runtime.  The downside of this inheritance is that we pay for the overhead
- * of the parent class construction/destruction without any real benefit.
- */
 class SkiaDisplayList {
 public:
     size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); }
@@ -156,7 +151,17 @@
     std::deque<RenderNodeDrawable> mChildNodes;
     std::deque<FunctorDrawable*> mChildFunctors;
     std::vector<SkImage*> mMutableImages;
-    std::vector<VectorDrawableRoot*> mVectorDrawables;
+private:
+    std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
+public:
+    void appendVD(VectorDrawableRoot* r) {
+        appendVD(r, SkMatrix::I());
+    }
+
+    void appendVD(VectorDrawableRoot* r, const SkMatrix& mat) {
+        mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
+    }
+
     std::vector<AnimatedImageDrawable*> mAnimatedImages;
     DisplayListData mDisplayList;
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5a47a29..0a28949 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -152,7 +152,9 @@
 
 void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
     mRecorder.drawVectorDrawable(tree);
-    mDisplayList->mVectorDrawables.push_back(tree);
+    SkMatrix mat;
+    this->getMatrix(&mat);
+    mDisplayList->appendVD(tree, mat);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1b3bd30..2957b14 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -41,6 +41,7 @@
 #include <sys/stat.h>
 #include <algorithm>
 
+#include <cstdint>
 #include <cstdlib>
 #include <functional>
 
@@ -510,6 +511,17 @@
     prepareAndDraw(nullptr);
 }
 
+SkISize CanvasContext::getNextFrameSize() const {
+    ReliableSurface* surface = mNativeSurface.get();
+    if (surface) {
+        SkISize size;
+        surface->query(NATIVE_WINDOW_WIDTH, &size.fWidth);
+        surface->query(NATIVE_WINDOW_HEIGHT, &size.fHeight);
+        return size;
+    }
+    return {INT32_MAX, INT32_MAX};
+}
+
 void CanvasContext::prepareAndDraw(RenderNode* node) {
     ATRACE_CALL();
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0bd080d..912b125 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -32,6 +32,7 @@
 #include <EGL/egl.h>
 #include <SkBitmap.h>
 #include <SkRect.h>
+#include <SkSize.h>
 #include <cutils/compiler.h>
 #include <gui/Surface.h>
 #include <utils/Functor.h>
@@ -112,7 +113,7 @@
     void setSurface(sp<Surface>&& surface);
     bool pauseSurface();
     void setStopped(bool stopped);
-    bool hasSurface() { return mNativeSurface.get(); }
+    bool hasSurface() const { return mNativeSurface.get(); }
     void allocateBuffers();
 
     void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
@@ -205,6 +206,8 @@
     // Must be called before setSurface
     void setRenderAheadDepth(uint32_t renderAhead);
 
+    SkISize getNextFrameSize() const;
+
 private:
     CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
                   IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 1b4cf7e..6fb164a 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -23,6 +23,7 @@
 #include "pipeline/skia/GLFunctorDrawable.h"
 #include "pipeline/skia/SkiaDisplayList.h"
 #include "renderthread/CanvasContext.h"
+#include "tests/common/TestContext.h"
 #include "tests/common/TestUtils.h"
 
 using namespace android;
@@ -50,13 +51,13 @@
     GLFunctorDrawable functorDrawable(nullptr, nullptr, &dummyCanvas);
     skiaDL->mChildFunctors.push_back(&functorDrawable);
     skiaDL->mMutableImages.push_back(nullptr);
-    skiaDL->mVectorDrawables.push_back(nullptr);
+    skiaDL->appendVD(nullptr);
     skiaDL->mProjectionReceiver = &drawable;
 
     ASSERT_FALSE(skiaDL->mChildNodes.empty());
     ASSERT_FALSE(skiaDL->mChildFunctors.empty());
     ASSERT_FALSE(skiaDL->mMutableImages.empty());
-    ASSERT_FALSE(skiaDL->mVectorDrawables.empty());
+    ASSERT_TRUE(skiaDL->hasVectorDrawables());
     ASSERT_FALSE(skiaDL->isEmpty());
     ASSERT_TRUE(skiaDL->mProjectionReceiver);
 
@@ -65,7 +66,7 @@
     ASSERT_TRUE(skiaDL->mChildNodes.empty());
     ASSERT_TRUE(skiaDL->mChildFunctors.empty());
     ASSERT_TRUE(skiaDL->mMutableImages.empty());
-    ASSERT_TRUE(skiaDL->mVectorDrawables.empty());
+    ASSERT_FALSE(skiaDL->hasVectorDrawables());
     ASSERT_TRUE(skiaDL->isEmpty());
     ASSERT_FALSE(skiaDL->mProjectionReceiver);
 }
@@ -110,7 +111,7 @@
     SkRect bounds = SkRect::MakeWH(200, 200);
     VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
     vectorDrawable.mutateStagingProperties()->setBounds(bounds);
-    skiaDL.mVectorDrawables.push_back(&vectorDrawable);
+    skiaDL.appendVD(&vectorDrawable);
 
     // ensure that the functor and vectorDrawable are properly synced
     TestUtils::runOnRenderThread([&](auto&) {
@@ -149,9 +150,14 @@
 
     SkiaDisplayList skiaDL;
 
+    // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+    // empty) in order to have PropertyChangeWillBeConsumed set.
+    const auto bounds = SkRect::MakeIWH(100, 100);
+
     // prepare with a clean VD
     VectorDrawableRoot cleanVD(new VectorDrawable::Group());
-    skiaDL.mVectorDrawables.push_back(&cleanVD);
+    cleanVD.mutateProperties()->setBounds(bounds);
+    skiaDL.appendVD(&cleanVD);
     cleanVD.getBitmapUpdateIfDirty();  // this clears the dirty bit
 
     ASSERT_FALSE(cleanVD.isDirty());
@@ -159,11 +165,12 @@
     TestUtils::MockTreeObserver observer;
     ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
                                                [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
-    ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
+    ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
 
     // prepare again this time adding a dirty VD
     VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
-    skiaDL.mVectorDrawables.push_back(&dirtyVD);
+    dirtyVD.mutateProperties()->setBounds(bounds);
+    skiaDL.appendVD(&dirtyVD);
 
     ASSERT_TRUE(dirtyVD.isDirty());
     ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
@@ -191,6 +198,169 @@
     canvasContext->destroy();
 }
 
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscreen) {
+    auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(
+            CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+
+    // Set up a Surface so that we can position the VectorDrawable offscreen.
+    test::TestContext testContext;
+    testContext.setRenderOffscreen(true);
+    auto surface = testContext.surface();
+    int width, height;
+    surface->query(NATIVE_WINDOW_WIDTH, &width);
+    surface->query(NATIVE_WINDOW_HEIGHT, &height);
+    canvasContext->setSurface(std::move(surface));
+
+    TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+
+    // The VectorDrawableRoot needs to have bounds on screen (and therefore not
+    // empty) in order to have PropertyChangeWillBeConsumed set.
+    const auto bounds = SkRect::MakeIWH(100, 100);
+
+    for (const SkRect b : {bounds.makeOffset(width, 0),
+                           bounds.makeOffset(0, height),
+                           bounds.makeOffset(-bounds.width(), 0),
+                           bounds.makeOffset(0, -bounds.height())}) {
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(b);
+        skiaDL.appendVD(&dirtyVD);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_FALSE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+    }
+
+    // The DamageAccumulator's transform can also result in the
+    // VectorDrawableRoot being offscreen.
+    for (const SkISize translate : { SkISize{width, 0},
+                                     SkISize{0, height},
+                                     SkISize{-width, 0},
+                                     SkISize{0, -height}}) {
+        Matrix4 mat4;
+        mat4.translate(translate.fWidth, translate.fHeight);
+        damageAccumulator.pushTransform(&mat4);
+
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(bounds);
+        skiaDL.appendVD(&dirtyVD);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_FALSE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+        damageAccumulator.popTransform();
+    }
+
+    // Another way to be offscreen: a matrix from the draw call.
+    for (const SkMatrix translate : { SkMatrix::MakeTrans(width, 0),
+                                      SkMatrix::MakeTrans(0, height),
+                                      SkMatrix::MakeTrans(-width, 0),
+                                      SkMatrix::MakeTrans(0, -height)}) {
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(bounds);
+        skiaDL.appendVD(&dirtyVD, translate);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_FALSE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+    }
+
+    // Verify that the matrices are combined in the right order.
+    {
+        // Rotate and then translate, so the VD is offscreen.
+        Matrix4 mat4;
+        mat4.loadRotate(180);
+        damageAccumulator.pushTransform(&mat4);
+
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(bounds);
+        SkMatrix translate = SkMatrix::MakeTrans(50, 50);
+        skiaDL.appendVD(&dirtyVD, translate);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_FALSE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+        damageAccumulator.popTransform();
+    }
+    {
+        // Switch the order of rotate and translate, so it is on screen.
+        Matrix4 mat4;
+        mat4.translate(50, 50);
+        damageAccumulator.pushTransform(&mat4);
+
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(bounds);
+        SkMatrix rotate;
+        rotate.setRotate(180);
+        skiaDL.appendVD(&dirtyVD, rotate);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_TRUE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+        damageAccumulator.popTransform();
+    }
+    {
+        // An AVD that is larger than the screen.
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(SkRect::MakeLTRB(-1, -1, width + 1, height + 1));
+        skiaDL.appendVD(&dirtyVD);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_TRUE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+    }
+    {
+        // An AVD whose bounds are not a rectangle after applying a matrix.
+        SkiaDisplayList skiaDL;
+        VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
+        dirtyVD.mutateProperties()->setBounds(bounds);
+        SkMatrix mat;
+        mat.setRotate(45, 50, 50);
+        skiaDL.appendVD(&dirtyVD, mat);
+
+        ASSERT_TRUE(dirtyVD.isDirty());
+        ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
+
+        TestUtils::MockTreeObserver observer;
+        ASSERT_TRUE(skiaDL.prepareListAndChildren(
+                observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
+        ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
+    }
+}
+
 TEST(SkiaDisplayList, updateChildren) {
     SkiaDisplayList skiaDL;
 
diff --git a/media/Android.bp b/media/Android.bp
index 8746046..70dacb2 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -20,10 +20,6 @@
         ],
     },
 
-    static_libs: [
-        "mediaplayer2-protos",
-    ],
-
     permitted_packages: [
         "android.media",
     ],
@@ -43,7 +39,6 @@
     name: "updatable-media-srcs",
     srcs: [
         ":mediasession2-srcs",
-        ":mediaplayer2-srcs",
     ],
 }
 
@@ -51,7 +46,6 @@
     name: "updatable-media-srcs-without-aidls",
     srcs : [
         ":mediasession2-srcs-without-aidls",
-        ":mediaplayer2-srcs",
     ],
 }
 
@@ -64,7 +58,6 @@
         "apex/java/android/media/IMediaSession2Service.aidl",
         "apex/java/android/media/MediaConstants.java",
         "apex/java/android/media/MediaController2.java",
-        "apex/java/android/media/MediaItem2.java",
         "apex/java/android/media/MediaSession2.java",
         "apex/java/android/media/MediaSession2Service.java",
         "apex/java/android/media/Session2Command.java",
@@ -110,8 +103,7 @@
     "--hide MissingPermission --hide BroadcastBehavior " +
     "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
     "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi " +
-    " --show-annotation android.annotation.TestApi "
+    "--hide HiddenTypedefConstant --show-annotation android.annotation.SystemApi "
 
 droidstubs {
     name: "updatable-media-stubs",
diff --git a/media/apex/java/android/media/BufferingParams.java b/media/apex/java/android/media/BufferingParams.java
index 83594d4..943f142 100644
--- a/media/apex/java/android/media/BufferingParams.java
+++ b/media/apex/java/android/media/BufferingParams.java
@@ -17,7 +17,6 @@
 package android.media;
 
 import android.annotation.IntDef;
-import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -64,7 +63,6 @@
  * <p>Users should use {@link Builder} to change {@link BufferingParams}.
  * @hide
  */
-@TestApi
 public final class BufferingParams implements Parcelable {
     private static final int BUFFERING_NO_MARK = -1;
 
diff --git a/media/apex/java/android/media/MediaItem2.java b/media/apex/java/android/media/MediaItem2.java
deleted file mode 100644
index ff0d43e..0000000
--- a/media/apex/java/android/media/MediaItem2.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaMetadata.METADATA_KEY_MEDIA_ID;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * A class with information on a single media item with the metadata information.
- * <p>
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
- * for consistent behavior across all devices.
- * <p>
- */
-public final class MediaItem2 implements Parcelable {
-    private static final String TAG = "MediaItem2";
-
-    // intentionally less than long.MAX_VALUE.
-    // Declare this first to avoid 'illegal forward reference'.
-    static final long LONG_MAX = 0x7ffffffffffffffL;
-
-    /**
-     * Used when a position is unknown.
-     *
-     * @see #getEndPosition()
-     */
-    public static final long POSITION_UNKNOWN = LONG_MAX;
-
-    public static final @android.annotation.NonNull Parcelable.Creator<MediaItem2> CREATOR =
-            new Parcelable.Creator<MediaItem2>() {
-                @Override
-                public MediaItem2 createFromParcel(Parcel in) {
-                    return new MediaItem2(in);
-                }
-
-                @Override
-                public MediaItem2[] newArray(int size) {
-                    return new MediaItem2[size];
-                }
-            };
-
-    private static final long UNKNOWN_TIME = -1;
-
-    private final long mStartPositionMs;
-    private final long mEndPositionMs;
-
-    private final Object mLock = new Object();
-
-    @GuardedBy("mLock")
-    private MediaMetadata mMetadata;
-    @GuardedBy("mLock")
-    private final List<Pair<OnMetadataChangedListener, Executor>> mListeners = new ArrayList<>();
-
-    /**
-     * Used by {@link MediaItem2.Builder}.
-     */
-    // Note: Needs to be protected when we want to allow 3rd party player to define customized
-    //       MediaItem2.
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    MediaItem2(Builder builder) {
-        this(builder.mMetadata, builder.mStartPositionMs, builder.mEndPositionMs);
-    }
-
-    /**
-     * Used by Parcelable.Creator.
-     */
-    // Note: Needs to be protected when we want to allow 3rd party player to define customized
-    //       MediaItem2.
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    MediaItem2(Parcel in) {
-        this(in.readParcelable(MediaItem2.class.getClassLoader()), in.readLong(), in.readLong());
-    }
-
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    MediaItem2(MediaItem2 item) {
-        this(item.mMetadata, item.mStartPositionMs, item.mEndPositionMs);
-    }
-
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
-    MediaItem2(@Nullable MediaMetadata metadata, long startPositionMs, long endPositionMs) {
-        if (startPositionMs > endPositionMs) {
-            throw new IllegalArgumentException("Illegal start/end position: "
-                    + startPositionMs + " : " + endPositionMs);
-        }
-        if (metadata != null && metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
-            long durationMs = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
-            if (durationMs != UNKNOWN_TIME && endPositionMs != POSITION_UNKNOWN
-                    && endPositionMs > durationMs) {
-                throw new IllegalArgumentException("endPositionMs shouldn't be greater than"
-                        + " duration in the metdata, endPositionMs=" + endPositionMs
-                        + ", durationMs=" + durationMs);
-            }
-        }
-        mMetadata = metadata;
-        mStartPositionMs = startPositionMs;
-        mEndPositionMs = endPositionMs;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
-        synchronized (mLock) {
-            sb.append("{mMetadata=").append(mMetadata);
-            sb.append(", mStartPositionMs=").append(mStartPositionMs);
-            sb.append(", mEndPositionMs=").append(mEndPositionMs);
-            sb.append('}');
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Sets metadata. If the metadata is not {@code null}, its id should be matched with this
-     * instance's media id.
-     *
-     * @param metadata metadata to update
-     * @see MediaMetadata#METADATA_KEY_MEDIA_ID
-     */
-    public void setMetadata(@Nullable MediaMetadata metadata) {
-        List<Pair<OnMetadataChangedListener, Executor>> listeners = new ArrayList<>();
-        synchronized (mLock) {
-            if (mMetadata != null && metadata != null
-                    && !TextUtils.equals(getMediaId(), metadata.getString(METADATA_KEY_MEDIA_ID))) {
-                Log.d(TAG, "MediaItem2's media ID shouldn't be changed");
-                return;
-            }
-            mMetadata = metadata;
-            listeners.addAll(mListeners);
-        }
-
-        for (Pair<OnMetadataChangedListener, Executor> pair : listeners) {
-            final OnMetadataChangedListener listener = pair.first;
-            pair.second.execute(new Runnable() {
-                @Override
-                public void run() {
-                    listener.onMetadataChanged(MediaItem2.this);
-                }
-            });
-        }
-    }
-
-    /**
-     * Gets the metadata of the media.
-     *
-     * @return metadata from the session
-     */
-    public @Nullable MediaMetadata getMetadata() {
-        synchronized (mLock) {
-            return mMetadata;
-        }
-    }
-
-    /**
-     * Return the position in milliseconds at which the playback will start.
-     * @return the position in milliseconds at which the playback will start
-     */
-    public long getStartPosition() {
-        return mStartPositionMs;
-    }
-
-    /**
-     * Return the position in milliseconds at which the playback will end.
-     * {@link #POSITION_UNKNOWN} means ending at the end of source content.
-     * @return the position in milliseconds at which the playback will end
-     */
-    public long getEndPosition() {
-        return mEndPositionMs;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mMetadata, 0);
-        dest.writeLong(mStartPositionMs);
-        dest.writeLong(mEndPositionMs);
-    }
-
-    /**
-     * Gets the media id for this item. If it's not {@code null}, it's a persistent unique key
-     * for the underlying media content.
-     *
-     * @return media Id from the session
-     */
-    @Nullable String getMediaId() {
-        synchronized (mLock) {
-            return mMetadata != null
-                    ? mMetadata.getString(METADATA_KEY_MEDIA_ID) : null;
-        }
-    }
-
-    void addOnMetadataChangedListener(Executor executor, OnMetadataChangedListener listener) {
-        synchronized (mLock) {
-            for (Pair<OnMetadataChangedListener, Executor> pair : mListeners) {
-                if (pair.first == listener) {
-                    return;
-                }
-            }
-            mListeners.add(new Pair<>(listener, executor));
-        }
-    }
-
-    void removeOnMetadataChangedListener(OnMetadataChangedListener listener) {
-        synchronized (mLock) {
-            for (int i = mListeners.size() - 1; i >= 0; i--) {
-                if (mListeners.get(i).first == listener) {
-                    mListeners.remove(i);
-                    return;
-                }
-            }
-        }
-    }
-
-    /**
-     * Builder for {@link MediaItem2}.
-     */
-    public static final class Builder {
-        @SuppressWarnings("WeakerAccess") /* synthetic access */
-        MediaMetadata mMetadata;
-        @SuppressWarnings("WeakerAccess") /* synthetic access */
-        long mStartPositionMs = 0;
-        @SuppressWarnings("WeakerAccess") /* synthetic access */
-        long mEndPositionMs = POSITION_UNKNOWN;
-
-        /**
-         * Set the metadata of this instance. {@code null} for unset.
-         *
-         * @param metadata metadata
-         * @return this instance for chaining
-         */
-        public @NonNull Builder setMetadata(@Nullable MediaMetadata metadata) {
-            mMetadata = metadata;
-            return this;
-        }
-
-        /**
-         * Sets the start position in milliseconds at which the playback will start.
-         * Any negative number is treated as 0.
-         *
-         * @param position the start position in milliseconds at which the playback will start
-         * @return the same Builder instance.
-         */
-        public @NonNull Builder setStartPosition(long position) {
-            if (position < 0) {
-                position = 0;
-            }
-            mStartPositionMs = position;
-            return this;
-        }
-
-        /**
-         * Sets the end position in milliseconds at which the playback will end.
-         * Any negative number is treated as maximum length of the media item.
-         *
-         * @param position the end position in milliseconds at which the playback will end
-         * @return the same Builder instance.
-         */
-        public @NonNull Builder setEndPosition(long position) {
-            if (position < 0) {
-                position = POSITION_UNKNOWN;
-            }
-            mEndPositionMs = position;
-            return this;
-        }
-
-        /**
-         * Build {@link MediaItem2}.
-         *
-         * @return a new {@link MediaItem2}.
-         */
-        public @NonNull MediaItem2 build() {
-            return new MediaItem2(this);
-        }
-    }
-
-    interface OnMetadataChangedListener {
-        void onMetadataChanged(MediaItem2 item);
-    }
-}
diff --git a/media/apex/java/android/media/Session2Command.java b/media/apex/java/android/media/Session2Command.java
index 7f73dc1..7c752e1 100644
--- a/media/apex/java/android/media/Session2Command.java
+++ b/media/apex/java/android/media/Session2Command.java
@@ -30,7 +30,7 @@
  * <p>
  * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
  * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomCommand()} shouldn't be {@code null}.
+ * {@link #getCustomAction()} shouldn't be {@code null}.
  * <p>
  * Refer to the
  * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
@@ -63,8 +63,8 @@
 
     private final int mCommandCode;
     // Nonnull if it's custom command
-    private final String mCustomCommand;
-    private final Bundle mExtras;
+    private final String mCustomAction;
+    private final Bundle mCustomExtras;
 
     /**
      * Constructor for creating a command predefined in AndroidX media2.
@@ -76,8 +76,8 @@
             throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
         }
         mCommandCode = commandCode;
-        mCustomCommand = null;
-        mExtras = null;
+        mCustomAction = null;
+        mCustomExtras = null;
     }
 
     /**
@@ -91,8 +91,8 @@
             throw new IllegalArgumentException("action shouldn't be null");
         }
         mCommandCode = COMMAND_CODE_CUSTOM;
-        mCustomCommand = action;
-        mExtras = extras;
+        mCustomAction = action;
+        mCustomExtras = extras;
     }
 
     /**
@@ -101,8 +101,8 @@
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     Session2Command(Parcel in) {
         mCommandCode = in.readInt();
-        mCustomCommand = in.readString();
-        mExtras = in.readBundle();
+        mCustomAction = in.readString();
+        mCustomExtras = in.readBundle();
     }
 
     /**
@@ -118,8 +118,8 @@
      * This will return {@code null} for a predefined command.
      */
     @Nullable
-    public String getCustomCommand() {
-        return mCustomCommand;
+    public String getCustomAction() {
+        return mCustomAction;
     }
 
     /**
@@ -127,8 +127,8 @@
      * This will return {@code null} for a predefined command.
      */
     @Nullable
-    public Bundle getExtras() {
-        return mExtras;
+    public Bundle getCustomExtras() {
+        return mCustomExtras;
     }
 
     @Override
@@ -142,8 +142,8 @@
             throw new IllegalArgumentException("parcel shouldn't be null");
         }
         dest.writeInt(mCommandCode);
-        dest.writeString(mCustomCommand);
-        dest.writeBundle(mExtras);
+        dest.writeString(mCustomAction);
+        dest.writeBundle(mCustomExtras);
     }
 
     @Override
@@ -153,12 +153,12 @@
         }
         Session2Command other = (Session2Command) obj;
         return mCommandCode == other.mCommandCode
-                && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+                && TextUtils.equals(mCustomAction, other.mCustomAction);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mCustomCommand, mCommandCode);
+        return Objects.hash(mCustomAction, mCommandCode);
     }
 
     /**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d347137..f8e43437 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4523,6 +4523,7 @@
      */
 
     /** @hide */
+    @TestApi
     @SystemApi
     public static final int SUCCESS = AudioSystem.SUCCESS;
     /**
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
deleted file mode 100644
index f704acd..0000000
--- a/media/java/android/media/MiniThumbFile.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.UnsupportedAppUsage;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Log;
-
-import dalvik.system.VMRuntime;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.util.Hashtable;
-
-/**
- * This class handles the mini-thumb file. A mini-thumb file consists
- * of blocks, indexed by id. Each block has BYTES_PER_MINTHUMB bytes in the
- * following format:
- *
- * 1 byte status (0 = empty, 1 = mini-thumb available)
- * 8 bytes magic (a magic number to match what's in the database)
- * 4 bytes data length (LEN)
- * LEN bytes jpeg data
- * (the remaining bytes are unused)
- *
- * @hide This file is shared between MediaStore and MediaProvider and should remained internal use
- *       only.
- * @deprecated thumbnails are now maintained in separate files, and this file
- *             format is no longer used.
- */
-@Deprecated
-public class MiniThumbFile {
-    private static final String TAG = "MiniThumbFile";
-    private static final int MINI_THUMB_DATA_FILE_VERSION = 4;
-    public static final int BYTES_PER_MINTHUMB = 10000;
-    private static final int HEADER_SIZE = 1 + 8 + 4;
-    private Uri mUri;
-    private RandomAccessFile mMiniThumbFile;
-    private FileChannel mChannel;
-    private ByteBuffer mBuffer;
-    private ByteBuffer mEmptyBuffer;
-    private static final Hashtable<String, MiniThumbFile> sThumbFiles =
-        new Hashtable<String, MiniThumbFile>();
-
-    /**
-     * We store different types of thumbnails in different files. To remain backward compatibility,
-     * we should hashcode of content://media/external/images/media remains the same.
-     */
-    @UnsupportedAppUsage
-    public static synchronized void reset() {
-        for (MiniThumbFile file : sThumbFiles.values()) {
-            file.deactivate();
-        }
-        sThumbFiles.clear();
-    }
-
-    public static synchronized MiniThumbFile instance(Uri uri) {
-        if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
-            throw new UnsupportedOperationException();
-        }
-        String type = uri.getPathSegments().get(1);
-        MiniThumbFile file = sThumbFiles.get(type);
-        // Log.v(TAG, "get minithumbfile for type: "+type);
-        if (file == null) {
-            file = new MiniThumbFile(
-                    Uri.parse("content://media/external/" + type + "/media"));
-            sThumbFiles.put(type, file);
-        }
-
-        return file;
-    }
-
-    private String randomAccessFilePath(int version) {
-        String directoryName =
-                Environment.getExternalStorageDirectory().toString()
-                + "/DCIM/.thumbnails";
-        return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode();
-    }
-
-    private void removeOldFile() {
-        String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - 1);
-        File oldFile = new File(oldPath);
-        if (oldFile.exists()) {
-            try {
-                oldFile.delete();
-            } catch (SecurityException ex) {
-                // ignore
-            }
-        }
-    }
-
-    private RandomAccessFile miniThumbDataFile() {
-        if (mMiniThumbFile == null) {
-            removeOldFile();
-            String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION);
-            File directory = new File(path).getParentFile();
-            if (!directory.isDirectory()) {
-                if (!directory.mkdirs()) {
-                    Log.e(TAG, "Unable to create .thumbnails directory "
-                            + directory.toString());
-                }
-            }
-            File f = new File(path);
-            try {
-                mMiniThumbFile = new RandomAccessFile(f, "rw");
-            } catch (IOException ex) {
-                // Open as read-only so we can at least read the existing
-                // thumbnails.
-                try {
-                    mMiniThumbFile = new RandomAccessFile(f, "r");
-                } catch (IOException ex2) {
-                    // ignore exception
-                }
-            }
-            if (mMiniThumbFile != null) {
-                mChannel = mMiniThumbFile.getChannel();
-            }
-        }
-        return mMiniThumbFile;
-    }
-
-    private MiniThumbFile(Uri uri) {
-        mUri = uri;
-        mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
-        mEmptyBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB);
-    }
-
-    public synchronized void deactivate() {
-        if (mMiniThumbFile != null) {
-            try {
-                mMiniThumbFile.close();
-                mMiniThumbFile = null;
-            } catch (IOException ex) {
-                // ignore exception
-            }
-        }
-    }
-
-    // Get the magic number for the specified id in the mini-thumb file.
-    // Returns 0 if the magic is not available.
-    public synchronized long getMagic(long id) {
-        // check the mini thumb file for the right data.  Right is
-        // defined as having the right magic number at the offset
-        // reserved for this "id".
-        RandomAccessFile r = miniThumbDataFile();
-        if (r != null) {
-            long pos = id * BYTES_PER_MINTHUMB;
-            FileLock lock = null;
-            try {
-                mBuffer.clear();
-                mBuffer.limit(1 + 8);
-
-                lock = mChannel.lock(pos, 1 + 8, true);
-                // check that we can read the following 9 bytes
-                // (1 for the "status" and 8 for the long)
-                if (mChannel.read(mBuffer, pos) == 9) {
-                    mBuffer.position(0);
-                    if (mBuffer.get() == 1) {
-                        return mBuffer.getLong();
-                    }
-                }
-            } catch (IOException ex) {
-                Log.v(TAG, "Got exception checking file magic: ", ex);
-            } catch (RuntimeException ex) {
-                // Other NIO related exception like disk full, read only channel..etc
-                Log.e(TAG, "Got exception when reading magic, id = " + id +
-                        ", disk full or mount read-only? " + ex.getClass());
-            } finally {
-                try {
-                    if (lock != null) lock.release();
-                }
-                catch (IOException ex) {
-                    // ignore it.
-                }
-            }
-        }
-        return 0;
-    }
-
-    public synchronized void eraseMiniThumb(long id) {
-        RandomAccessFile r = miniThumbDataFile();
-        if (r != null) {
-            long pos = id * BYTES_PER_MINTHUMB;
-            FileLock lock = null;
-            try {
-                mBuffer.clear();
-                mBuffer.limit(1 + 8);
-
-                lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
-                // check that we can read the following 9 bytes
-                // (1 for the "status" and 8 for the long)
-                if (mChannel.read(mBuffer, pos) == 9) {
-                    mBuffer.position(0);
-                    if (mBuffer.get() == 1) {
-                        long currentMagic = mBuffer.getLong();
-                        if (currentMagic == 0) {
-                            // there is no thumbnail stored here
-                            Log.i(TAG, "no thumbnail for id " + id);
-                            return;
-                        }
-                        // zero out the thumbnail slot
-                        // Log.v(TAG, "clearing slot " + id + ", magic " + currentMagic
-                        //         + " at offset " + pos);
-                        mChannel.write(mEmptyBuffer, pos);
-                    }
-                } else {
-                    // Log.v(TAG, "No slot");
-                }
-            } catch (IOException ex) {
-                Log.v(TAG, "Got exception checking file magic: ", ex);
-            } catch (RuntimeException ex) {
-                // Other NIO related exception like disk full, read only channel..etc
-                Log.e(TAG, "Got exception when reading magic, id = " + id +
-                        ", disk full or mount read-only? " + ex.getClass());
-            } finally {
-                try {
-                    if (lock != null) lock.release();
-                }
-                catch (IOException ex) {
-                    // ignore it.
-                }
-            }
-        } else {
-            // Log.v(TAG, "No data file");
-        }
-    }
-
-    public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic)
-            throws IOException {
-        RandomAccessFile r = miniThumbDataFile();
-        if (r == null) return;
-
-        long pos = id * BYTES_PER_MINTHUMB;
-        FileLock lock = null;
-        try {
-            if (data != null) {
-                if (data.length > BYTES_PER_MINTHUMB - HEADER_SIZE) {
-                    // not enough space to store it.
-                    return;
-                }
-                mBuffer.clear();
-                mBuffer.put((byte) 1);
-                mBuffer.putLong(magic);
-                mBuffer.putInt(data.length);
-                mBuffer.put(data);
-                mBuffer.flip();
-
-                lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false);
-                mChannel.write(mBuffer, pos);
-            }
-        } catch (IOException ex) {
-            Log.e(TAG, "couldn't save mini thumbnail data for "
-                    + id + "; ", ex);
-            throw ex;
-        } catch (RuntimeException ex) {
-            // Other NIO related exception like disk full, read only channel..etc
-            Log.e(TAG, "couldn't save mini thumbnail data for "
-                    + id + "; disk full or mount read-only? " + ex.getClass());
-        } finally {
-            try {
-                if (lock != null) lock.release();
-            }
-            catch (IOException ex) {
-                // ignore it.
-            }
-        }
-    }
-
-    /**
-     * Gallery app can use this method to retrieve mini-thumbnail. Full size
-     * images share the same IDs with their corresponding thumbnails.
-     *
-     * @param id the ID of the image (same of full size image).
-     * @param data the buffer to store mini-thumbnail.
-     */
-    public synchronized byte [] getMiniThumbFromFile(long id, byte [] data) {
-        RandomAccessFile r = miniThumbDataFile();
-        if (r == null) return null;
-
-        long pos = id * BYTES_PER_MINTHUMB;
-        FileLock lock = null;
-        try {
-            mBuffer.clear();
-            lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, true);
-            int size = mChannel.read(mBuffer, pos);
-            if (size > 1 + 8 + 4) { // flag, magic, length
-                mBuffer.position(0);
-                byte flag = mBuffer.get();
-                long magic = mBuffer.getLong();
-                int length = mBuffer.getInt();
-
-                if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
-                        data.length >= length) {
-                    mBuffer.get(data, 0, length);
-                    return data;
-                }
-            }
-        } catch (IOException ex) {
-            Log.w(TAG, "got exception when reading thumbnail id=" + id + ", exception: " + ex);
-        } catch (RuntimeException ex) {
-            // Other NIO related exception like disk full, read only channel..etc
-            Log.e(TAG, "Got exception when reading thumbnail, id = " + id +
-                    ", disk full or mount read-only? " + ex.getClass());
-        } finally {
-            try {
-                if (lock != null) lock.release();
-            }
-            catch (IOException ex) {
-                // ignore it.
-            }
-        }
-        return null;
-    }
-}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index fefb0d7..e207721 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -495,15 +495,17 @@
         if (mCursor == null || !mCursor.moveToPosition(position)) {
             return null;
         }
-        
-        return getUriFromCursor(mCursor);
+
+        return getUriFromCursor(mContext, mCursor);
     }
 
-    private static Uri getUriFromCursor(Cursor cursor) {
-        return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
-                .getLong(ID_COLUMN_INDEX));
+    private static Uri getUriFromCursor(Context context, Cursor cursor) {
+        final Uri uri = ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)),
+                cursor.getLong(ID_COLUMN_INDEX));
+        final Uri canonicalized = context.getContentResolver().canonicalize(uri);
+        return (canonicalized != null) ? canonicalized : uri;
     }
-    
+
     /**
      * Gets the position of a {@link Uri} within this {@link RingtoneManager}.
      * 
@@ -569,7 +571,7 @@
             Uri uri = null;
             
             if (cursor.moveToFirst()) {
-                uri = getUriFromCursor(cursor);
+                uri = getUriFromCursor(context, cursor);
             }
             cursor.close();
             
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 1cd60f7..39474e1 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -416,6 +416,7 @@
      * @param devices list of devices to which the audio stream of the application may be routed.
      * @return true if the change was successful, false otherwise.
      */
+    @TestApi
     @SystemApi
     public boolean setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
         if (devices == null) {
@@ -457,6 +458,7 @@
      * @param uid UID of the application affected.
      * @return true if the change was successful, false otherwise.
      */
+    @TestApi
     @SystemApi
     public boolean removeUidDeviceAffinity(int uid) {
         synchronized (mLock) {
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 55c9361..81c5bcd 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -52,6 +52,7 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.TrafficStatsConstants;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
@@ -238,7 +239,8 @@
                 if (isFinishing() || isDestroyed()) return;
                 HttpURLConnection urlConnection = null;
                 int httpResponseCode = 500;
-                int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+                int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                        TrafficStatsConstants.TAG_SYSTEM_PROBE);
                 try {
                     urlConnection = (HttpURLConnection) mNetwork.openConnection(
                             new URL(mCm.getCaptivePortalServerUrl()));
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 1544adb..7860f36 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -238,7 +238,7 @@
         }
         mSingleThreadExecutor.submit(() -> {
             NotificationEntry entry =
-                    new NotificationEntry(mPackageManager, sbn, channel, mSmsHelper);
+                    new NotificationEntry(mPackageManager, sbn.cloneLight(), channel, mSmsHelper);
             SmartActionsHelper.SmartSuggestions suggestions = mSmartActionsHelper.suggest(entry);
             if (DEBUG) {
                 Log.d(TAG, String.format(
@@ -272,6 +272,9 @@
                 final int importance = entry.getImportance() < IMPORTANCE_LOW
                         ? entry.getImportance() : IMPORTANCE_LOW;
                 signals.putInt(KEY_IMPORTANCE, importance);
+            } else {
+                // Even if no change is made, send an identity adjustment for metric logging.
+                signals.putInt(KEY_IMPORTANCE, entry.getImportance());
             }
         }
 
@@ -293,7 +296,7 @@
             Ranking ranking = getRanking(sbn.getKey(), rankingMap);
             if (ranking != null && ranking.getChannel() != null) {
                 NotificationEntry entry = new NotificationEntry(mPackageManager,
-                        sbn, ranking.getChannel(), mSmsHelper);
+                        sbn.cloneLight(), ranking.getChannel(), mSmsHelper);
                 String key = getKey(
                         sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
                 ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 0d687d4..10360a3 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -338,7 +338,7 @@
                 createTextClassifierEventBuilder(
                         TextClassifierEvent.TYPE_SMART_ACTION, session.resultId)
                         .setEntityTypes(ConversationAction.TYPE_TEXT_REPLY)
-                        .setScore(session.repliesScores.getOrDefault(reply, 0f))
+                        .setScores(session.repliesScores.getOrDefault(reply, 0f))
                         .build();
         mTextClassifier.onTextClassifierEvent(textClassifierEvent);
     }
@@ -381,11 +381,9 @@
                 .build();
     }
 
-    private TextClassifierEvent.Builder createTextClassifierEventBuilder(
+    private TextClassifierEvent.ConversationActionsEvent.Builder createTextClassifierEventBuilder(
             int eventType, String resultId) {
-        return new TextClassifierEvent.Builder(
-                TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
-                .setEventTime(System.currentTimeMillis())
+        return new TextClassifierEvent.ConversationActionsEvent.Builder(eventType)
                 .setEventContext(
                         new TextClassificationContext.Builder(
                                 mContext.getPackageName(), TextClassifier.WIDGET_TYPE_NOTIFICATION)
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
index ebcaee8..dfa1ea0 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionsHelperTest.java
@@ -330,7 +330,9 @@
         List<TextClassifierEvent> events = argumentCaptor.getAllValues();
         assertTextClassifierEvent(events.get(0), TextClassifierEvent.TYPE_ACTIONS_GENERATED);
         assertTextClassifierEvent(events.get(1), TextClassifierEvent.TYPE_SMART_ACTION);
-        assertThat(events.get(1).getScore()).isEqualTo(SCORE);
+        float[] scores = events.get(1).getScores();
+        assertThat(scores).hasLength(1);
+        assertThat(scores[0]).isEqualTo(SCORE);
     }
 
     @Test
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index 64adc0d..af0e3bb 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -65,6 +65,7 @@
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.internal.util.TrafficStatsConstants;
 import com.android.internal.util.WakeupMessage;
 
 import java.io.FileDescriptor;
@@ -329,7 +330,8 @@
     }
 
     private boolean initUdpSocket() {
-        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP);
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                TrafficStatsConstants.TAG_SYSTEM_DHCP);
         try {
             mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
             SocketUtils.bindSocketToInterface(mUdpSock, mIfaceName);
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index 8832eaa..d21b5f7 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -16,7 +16,6 @@
 
 package android.net.dhcp;
 
-import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
 import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
 import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME;
 import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
@@ -33,6 +32,7 @@
 import static android.system.OsConstants.SO_BROADCAST;
 import static android.system.OsConstants.SO_REUSEADDR;
 
+import static com.android.internal.util.TrafficStatsConstants.TAG_SYSTEM_DHCP_SERVER;
 import static com.android.server.util.NetworkStackConstants.INFINITE_LEASE;
 import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ALL;
 import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ANY;
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 2a61250..27d4203 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -98,6 +98,7 @@
 import com.android.internal.util.RingBufferIndices;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.internal.util.TrafficStatsConstants;
 import com.android.networkstack.R;
 import com.android.networkstack.metrics.DataStallDetectionStats;
 import com.android.networkstack.metrics.DataStallStatsUtils;
@@ -1478,7 +1479,8 @@
         int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
         String redirectUrl = null;
         final Stopwatch probeTimer = new Stopwatch().start();
-        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                TrafficStatsConstants.TAG_SYSTEM_PROBE);
         try {
             urlConnection = (HttpURLConnection) mNetwork.openConnection(url);
             urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index 87b5b57..4f4aef0 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -76,11 +76,13 @@
     public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
         final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
         int targetUserId = UserHandle.myUserId();
-        if (admin != null && admin.user != null
-                && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
-            targetUserId = admin.user.getIdentifier();
+        if (admin != null) {
+            if (admin.user != null
+                    && isCurrentUserOrProfile(context, admin.user.getIdentifier())) {
+                targetUserId = admin.user.getIdentifier();
+            }
+            intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
         }
-        intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
         context.startActivityAsUser(intent, UserHandle.of(targetUserId));
     }
 
diff --git a/packages/SettingsLib/res/layout/settings_dialog_title.xml b/packages/SettingsLib/res/layout/settings_dialog_title.xml
new file mode 100644
index 0000000..1e065e0
--- /dev/null
+++ b/packages/SettingsLib/res/layout/settings_dialog_title.xml
@@ -0,0 +1,55 @@
+<?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:id="@+id/settings_title_panel"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/settings_title_template"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:gravity="center"
+        android:paddingStart="?android:attr/dialogPreferredPadding"
+        android:paddingEnd="?android:attr/dialogPreferredPadding"
+        android:paddingTop="@*android:dimen/dialog_padding_top_material">
+
+        <ImageView
+            android:id="@+id/settings_icon"
+            android:layout_width="24dip"
+            android:layout_height="24dip"
+            android:layout_marginBottom="12dip" />
+
+        <TextView
+            android:id="@+id/settings_title"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAlignment="center"
+            style="?android:attr/windowTitleStyle" />
+    </LinearLayout>
+
+    <Space
+        android:id="@+id/settings_title_divider"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="@*android:dimen/dialog_title_divider_material" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index eff02d2..257943e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -83,6 +83,8 @@
     // Dual tone implies that battery level is a clipped overlay over top of the whole shape
     private var dualTone = false
 
+    private var batteryLevel = 0
+
     private val invalidateRunnable: () -> Unit = {
         invalidateSelf()
     }
@@ -177,9 +179,9 @@
         unifiedPath.reset()
         levelPath.reset()
         levelRect.set(fillRect)
-        val fillFraction = level / 100f
+        val fillFraction = batteryLevel / 100f
         val fillTop =
-                if (level >= 95)
+                if (batteryLevel >= 95)
                     fillRect.top
                 else
                     fillRect.top + (fillRect.height() * (1 - fillFraction))
@@ -223,7 +225,7 @@
             fillPaint.color = levelColor
 
             // Show colorError below this level
-            if (level <= Companion.CRITICAL_LEVEL && !charging) {
+            if (batteryLevel <= Companion.CRITICAL_LEVEL && !charging) {
                 c.save()
                 c.clipPath(scaledFill)
                 c.drawPath(levelPath, fillPaint)
@@ -310,13 +312,13 @@
      */
     public open fun setBatteryLevel(l: Int) {
         invertFillIcon = if (l >= 67) true else if (l <= 33) false else invertFillIcon
-        level = l
-        levelColor = batteryColorForLevel(level)
+        batteryLevel = l
+        levelColor = batteryColorForLevel(batteryLevel)
         invalidateSelf()
     }
 
     public fun getBatteryLevel(): Int {
-        return level
+        return batteryLevel
     }
 
     override fun onBoundsChange(bounds: Rect?) {
@@ -343,7 +345,7 @@
         dualToneBackgroundFill.color = bgColor
 
         // Also update the level color, since fillColor may have changed
-        levelColor = batteryColorForLevel(level)
+        levelColor = batteryColorForLevel(batteryLevel)
 
         invalidateSelf()
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 2b5a4e0..11c799e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib;
 
+import static android.app.admin.DevicePolicyManager.EXTRA_RESTRICTION;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
@@ -28,11 +29,13 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
@@ -42,6 +45,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -283,6 +287,26 @@
         assertThat(profile).isNull();
     }
 
+    @Test
+    public void sendShowAdminSupportDetailsIntent_extraRestrictionProvided() {
+        EnforcedAdmin enforcedAdmin = new EnforcedAdmin();
+        enforcedAdmin.enforcedRestriction = "Dummy";
+        RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, enforcedAdmin);
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
+        assertThat(intentCaptor.getValue().getExtra(EXTRA_RESTRICTION)).isEqualTo("Dummy");
+    }
+
+    @Test
+    public void sendShowAdminSupportDetailsIntent_noExtraRestriction() {
+        RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, null);
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
+        assertThat(intentCaptor.getValue().getExtra(EXTRA_RESTRICTION)).isNull();
+    }
+
     private UserInfo setUpUser(int userId, ComponentName[] admins) {
         UserInfo userInfo = new UserInfo(userId, "primary", 0);
         when(mUserManager.getUserInfo(userId)).thenReturn(userInfo);
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
similarity index 100%
rename from packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_thumbnail.png
rename to packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
deleted file mode 100644
index 2bfd655..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_thumbnail.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_frame.xml b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
new file mode 100644
index 0000000..a663ac8
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_frame.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="250dp"
+    android:width="250dp"
+    android:viewportHeight="380"
+    android:viewportWidth="380">
+    <path android:fillColor="#000000" android:pathData="M190,190m0,2a2,2 0,1 1,0 -4a2,2 0,1 1,0 4"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
new file mode 100644
index 0000000..c7b6d60
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_hour_hand.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="250dp"
+    android:width="250dp"
+    android:viewportHeight="380"
+    android:viewportWidth="380">
+    <path android:fillColor="#777777" android:fillType="evenOdd" android:pathData="M203,190C203,185.398 200.608,181.354 197,179.044L197,58C197,54.134 193.866,51 190,51C186.134,51 183,54.134 183,58L183,179.043C179.392,181.354 177,185.397 177,190C177,197.18 182.82,203 190,203C197.18,203 203,197.18 203,190Z"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
new file mode 100644
index 0000000..458275b
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/analog_minute_hand.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="250dp"
+    android:width="250dp"
+    android:viewportHeight="380"
+    android:viewportWidth="380">
+    <path android:fillColor="#FFFFFF" android:pathData="M192,182.252C195.45,183.14 198,186.272 198,190C198,194.418 194.418,198 190,198C185.582,198 182,194.418 182,190C182,186.272 184.55,183.14 188,182.252L188,10C188,8.895 188.895,8 190,8C191.105,8 192,8.895 192,10L192,182.252Z"/>
+</vector>
diff --git a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml b/packages/SystemUI/res-keyguard/layout/analog_clock.xml
similarity index 67%
rename from packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
rename to packages/SystemUI/res-keyguard/layout/analog_clock.xml
index dd25df8..cf6d35ee2 100644
--- a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/analog_clock.xml
@@ -35,9 +35,27 @@
       android:format24Hour="@string/keyguard_widget_24_hours_format"
       android:elegantTextHeight="false"
   />
-  <com.android.keyguard.clock.StretchAnalogClock
+  <com.android.keyguard.clock.ImageClock
       android:id="@+id/analog_clock"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent"
-  />
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+  >
+    <ImageView
+        android:id="@+id/hour_hand"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/analog_hour_hand"
+    />
+    <ImageView
+        android:id="@+id/minute_hand"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/analog_minute_hand"
+    />
+    <ImageView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/analog_frame"
+    />
+  </com.android.keyguard.clock.ImageClock>
 </com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 4738887..1e98189 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -413,9 +413,6 @@
     <string name="clock_title_bubble" translatable="false">Bubble</string>
     <!-- Title for Stretch clock face that will appear in the picker app next to a preview image of
          the clock face. [CHAR LIMIT=8] -->
-    <string name="clock_title_stretch" translatable="false">Stretch</string>
-    <!-- Title for Typographic clock face that will appear in the picker app next to a preview image of
-         the clock face. [CHAR LIMIT=8] -->
-    <string name="clock_title_type" translatable="false">Type</string>
+    <string name="clock_title_analog" translatable="false">Analog</string>
 
 </resources>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index f34161e..81d44cf 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -44,8 +44,7 @@
             android:padding="0dp"
             android:gravity="center"
             android:ellipsize="marquee"
-            android:textAppearance="@style/TextAppearance.QS.TileLabel"
-            android:textColor="?android:attr/textColorPrimary"/>
+            android:textAppearance="@style/TextAppearance.QS.TileLabel"/>
 
         <ImageView android:id="@+id/restricted_padlock"
             android:layout_width="@dimen/qs_tile_text_size"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 444cabfc..f121c8e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1331,6 +1331,14 @@
     <!-- Content description for accessibility: Clear the odi caption tool tip. [CHAR LIMIT=NONE] -->
     <string name="accessibility_volume_close_odi_captions_tip">Close captions tip</string>
 
+    <!-- Content description for accessibility: Captions button. [CHAR LIMIT=NONE] -->
+    <string name="volume_odi_captions_content_description">Captions overlay</string>
+
+    <!-- Content description for accessibility: Hint if click will enable. [CHAR LIMIT=NONE] -->
+    <string name="volume_odi_captions_hint_enable">enable</string>
+    <!-- Content description for accessibility: Hint if click will disable. [CHAR LIMIT=NONE] -->
+    <string name="volume_odi_captions_hint_disable">disable</string>
+
     <!-- content description for audio output chooser [CHAR LIMIT=NONE]-->
     <string name="accessibility_output_chooser">Switch output device</string>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 64517ba..eca3926 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -16,14 +16,22 @@
 
 package com.android.keyguard;
 
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
+
+import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -36,6 +44,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -113,6 +122,17 @@
         }
     };
 
+    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveMobileDataSubscription = subId;
+            if (mKeyguardUpdateMonitor != null) {
+                updateCarrierText();
+            }
+        }
+    };
+
     /**
      * The status of this lock screen. Primarily used for widgets on LockScreen.
      */
@@ -200,6 +220,8 @@
      * @param callback Callback to provide text updates
      */
     public void setListening(CarrierTextCallback callback) {
+        TelephonyManager telephonyManager = ((TelephonyManager) mContext
+                .getSystemService(Context.TELEPHONY_SERVICE));
         if (callback != null) {
             mCarrierTextCallback = callback;
             if (ConnectivityManager.from(mContext).isNetworkSupported(
@@ -207,6 +229,8 @@
                 mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
                 mKeyguardUpdateMonitor.registerCallback(mCallback);
                 mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+                telephonyManager.listen(mPhoneStateListener,
+                        LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
             } else {
                 // Don't listen and clear out the text when the device isn't a phone.
                 mKeyguardUpdateMonitor = null;
@@ -218,6 +242,35 @@
                 mKeyguardUpdateMonitor.removeCallback(mCallback);
                 mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
             }
+            telephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
+        }
+    }
+
+    /**
+     * STOPSHIP(b/130246708) remove when no longer needed for testing purpose.
+     * @param subscriptions
+     */
+    private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
+        if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
+            SubscriptionInfo info1 = subscriptions.get(0);
+            SubscriptionInfo info2 = subscriptions.get(1);
+            if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
+                // If both subscriptions are primary, show both.
+                if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
+
+                // If carrier required, always show signal bar of primary subscription.
+                // Otherwise, show whichever subscription is currently active for Internet.
+                boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
+                        .getBoolean(CarrierConfigManager
+                        .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
+                if (alwaysShowPrimary) {
+                    subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
+                } else {
+                    subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
+                            ? info2 : info1);
+                }
+
+            }
         }
     }
 
@@ -226,7 +279,17 @@
         boolean anySimReadyAndInService = false;
         CharSequence displayText = null;
 
-        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+        // STOPSHIP(b/130246708) revert to mKeyguardUpdateMonitor.getSubscriptionInfo(false).
+        SubscriptionManager subscriptionManager = ((SubscriptionManager) mContext.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE));
+        List<SubscriptionInfo> subs = subscriptionManager.getActiveSubscriptionInfoList(false);
+
+        if (subs == null) {
+            subs = new ArrayList<>();
+        } else {
+            filterMobileSubscriptionInSameGroup(subs);
+        }
+
         final int numSubs = subs.size();
         final int[] subsIds = new int[numSubs];
         // This array will contain in position i, the index of subscription in slot ID i.
@@ -311,20 +374,23 @@
 
         displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
                 allSimsMissing);
+        boolean airplaneMode = false;
         // APM (airplane mode) != no carrier state. There are carrier services
         // (e.g. WFC = Wi-Fi calling) which may operate in APM.
         if (!anySimReadyAndInService && WirelessUtils.isAirplaneModeOn(mContext)) {
             displayText = getAirplaneModeMessage();
+            airplaneMode = true;
         }
 
-        if (TextUtils.isEmpty(displayText)) {
+        if (TextUtils.isEmpty(displayText) && !airplaneMode) {
             displayText = TextUtils.join(mSeparator, carrierNames);
         }
         final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
                 displayText,
                 carrierNames,
                 !allSimsMissing,
-                subsIds);
+                subsIds,
+                airplaneMode);
         postToCallback(info);
     }
 
@@ -525,14 +591,22 @@
         public final CharSequence[] listOfCarriers;
         public final boolean anySimReady;
         public final int[] subscriptionIds;
+        public boolean airplaneMode;
 
         @VisibleForTesting
         public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
                 boolean anySimReady, int[] subscriptionIds) {
+            this(carrierText, listOfCarriers, anySimReady, subscriptionIds, false);
+        }
+
+        @VisibleForTesting
+        public CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers,
+                boolean anySimReady, int[] subscriptionIds, boolean airplaneMode) {
             this.carrierText = carrierText;
             this.listOfCarriers = listOfCarriers;
             this.anySimReady = anySimReady;
             this.subscriptionIds = subscriptionIds;
+            this.airplaneMode = airplaneMode;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fd55708..1d19fec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -665,9 +665,9 @@
         boolean wasRunning = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
         boolean isRunning = fingerprintRunningState == BIOMETRIC_STATE_RUNNING;
         mFingerprintRunningState = fingerprintRunningState;
-        if (DEBUG) Log.v(TAG, "Fingerprint State: " + mFingerprintRunningState);
+        Log.d(TAG, "fingerprintRunningState: " + mFingerprintRunningState);
         // Clients of KeyguardUpdateMonitor don't care about the internal state about the
-        // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+        // asynchronousness of the cancel cycle. So only notify them if the actually running state
         // has changed.
         if (wasRunning != isRunning) {
             notifyFingerprintRunningStateChanged();
@@ -818,9 +818,9 @@
         boolean wasRunning = mFaceRunningState == BIOMETRIC_STATE_RUNNING;
         boolean isRunning = faceRunningState == BIOMETRIC_STATE_RUNNING;
         mFaceRunningState = faceRunningState;
-        if (DEBUG) Log.v(TAG, "Face State: " + mFaceRunningState);
+        Log.d(TAG, "faceRunningState: " + mFaceRunningState);
         // Clients of KeyguardUpdateMonitor don't care about the internal state or about the
-        // asynchronousness of the cancel cycle. So only notify them if the actualy running state
+        // asynchronousness of the cancel cycle. So only notify them if the actually running state
         // has changed.
         if (wasRunning != isRunning) {
             notifyFaceRunningStateChanged();
@@ -2045,7 +2045,7 @@
      */
     public void onKeyguardVisibilityChanged(boolean showing) {
         checkIsHandlerThread();
-        if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+        Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
         mKeyguardIsVisible = showing;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
similarity index 90%
rename from packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
rename to packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 81b6a60..1652121 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -35,7 +35,7 @@
 /**
  * Controller for Stretch clock that can appear on lock screen and AOD.
  */
-public class StretchAnalogClockController implements ClockPlugin {
+public class AnalogClockController implements ClockPlugin {
 
     /**
      * Resources used to get title and thumbnail.
@@ -60,9 +60,9 @@
     /**
      * Custom clock shown on AOD screen and behind stack scroller on lock.
      */
-    private View mBigClockView;
+    private ClockLayout mBigClockView;
     private TextClock mDigitalClock;
-    private StretchAnalogClock mAnalogClock;
+    private ImageClock mAnalogClock;
 
     /**
      * Small clock shown on lock screen above stack scroller.
@@ -82,7 +82,7 @@
      * @param inflater Inflater used to inflate custom clock views.
      * @param colorExtractor Extracts accent color from wallpaper.
      */
-    public StretchAnalogClockController(Resources res, LayoutInflater inflater,
+    public AnalogClockController(Resources res, LayoutInflater inflater,
             SysuiColorExtractor colorExtractor) {
         mResources = res;
         mLayoutInflater = inflater;
@@ -90,7 +90,7 @@
     }
 
     private void createViews() {
-        mBigClockView = mLayoutInflater.inflate(R.layout.stretchanalog_clock, null);
+        mBigClockView = (ClockLayout) mLayoutInflater.inflate(R.layout.analog_clock, null);
         mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
         mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
 
@@ -114,17 +114,17 @@
 
     @Override
     public String getName() {
-        return "stretch";
+        return "analog";
     }
 
     @Override
     public String getTitle() {
-        return mResources.getString(R.string.clock_title_stretch);
+        return mResources.getString(R.string.clock_title_analog);
     }
 
     @Override
     public Bitmap getThumbnail() {
-        return BitmapFactory.decodeResource(mResources, R.drawable.stretch_thumbnail);
+        return BitmapFactory.decodeResource(mResources, R.drawable.analog_thumbnail);
     }
 
     @Override
@@ -175,13 +175,14 @@
         }
         final int length = colorPalette.length;
         mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
-        mAnalogClock.setClockColor(colorPalette[Math.max(0, length - 5)],
+        mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 5)],
                 colorPalette[Math.max(0, length - 2)]);
     }
 
     @Override
     public void onTimeTick() {
         mAnalogClock.onTimeChanged();
+        mBigClockView.onTimeChanged();
         mDigitalClock.refresh();
         mLockClock.refresh();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index d30f45f..6069a5e 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -60,7 +60,7 @@
     /**
      * Custom clock shown on AOD screen and behind stack scroller on lock.
      */
-    private View mView;
+    private ClockLayout mView;
     private TextClock mDigitalClock;
     private ImageClock mAnalogClock;
 
@@ -90,7 +90,7 @@
     }
 
     private void createViews() {
-        mView = mLayoutInflater.inflate(R.layout.bubble_clock, null);
+        mView = (ClockLayout) mLayoutInflater.inflate(R.layout.bubble_clock, null);
         mDigitalClock = (TextClock) mView.findViewById(R.id.digital_clock);
         mAnalogClock = (ImageClock) mView.findViewById(R.id.analog_clock);
 
@@ -186,6 +186,7 @@
     @Override
     public void onTimeTick() {
         mAnalogClock.onTimeChanged();
+        mView.onTimeChanged();
         mDigitalClock.refresh();
         mLockClock.refresh();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 7ffee5d..55088a8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -32,6 +32,7 @@
  */
 public class ClockLayout extends FrameLayout {
 
+    private static final int ANALOG_CLOCK_SHIFT_FACTOR = 3;
     /**
      * Clock face views.
      */
@@ -73,7 +74,14 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
+        positionChildren();
+    }
 
+    void onTimeChanged() {
+        positionChildren();
+    }
+
+    private void positionChildren() {
         final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
                 - mBurnInPreventionOffsetX;
         final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
@@ -89,9 +97,9 @@
         // Put the analog clock in the middle of the screen.
         if (mAnalogClock != null) {
             mAnalogClock.setX(Math.max(0f, 0.5f * (getWidth() - mAnalogClock.getWidth()))
-                    + offsetX);
+                    + ANALOG_CLOCK_SHIFT_FACTOR * offsetX);
             mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
-                    + offsetY);
+                    + ANALOG_CLOCK_SHIFT_FACTOR * offsetY);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index e373ca1..06488b8 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -142,8 +142,7 @@
 
         addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
         addBuiltinClock(() -> new BubbleClockController(res, layoutInflater, colorExtractor));
-        addBuiltinClock(() -> new StretchAnalogClockController(res, layoutInflater,
-                colorExtractor));
+        addBuiltinClock(() -> new AnalogClockController(res, layoutInflater, colorExtractor));
 
         // Store the size of the display for generation of clock preview.
         DisplayMetrics dm = res.getDisplayMetrics();
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
deleted file mode 100644
index 8cdd632..0000000
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.keyguard.clock;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * Analog clock where the minute hand extends off of the screen.
- */
-public class StretchAnalogClock extends View {
-
-    private static final int DEFAULT_COLOR = Color.parseColor("#F5C983");
-    private static final float HOUR_STROKE_WIDTH = 60f;
-    private static final float MINUTE_STROKE_WIDTH = 20f;
-    private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 80f;
-
-    private final Paint mHourPaint = new Paint();
-    private final Paint mMinutePaint = new Paint();
-    private Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
-    private TimeZone mTimeZone;
-
-    public StretchAnalogClock(Context context) {
-        this(context, null);
-    }
-
-    public StretchAnalogClock(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        init();
-    }
-
-    /**
-     * Call when the time changes to update the clock hands.
-     */
-    public void onTimeChanged() {
-        mTime.setTimeInMillis(System.currentTimeMillis());
-        invalidate();
-    }
-
-    /**
-     * Call when the time zone has changed to update clock hands.
-     *
-     * @param timeZone The updated time zone that will be used.
-     */
-    public void onTimeZoneChanged(TimeZone timeZone) {
-        mTime.setTimeZone(timeZone);
-    }
-
-    /**
-     * Set the colors to use on the clock face.
-     * @param dark Darker color obtained from color palette.
-     * @param light Lighter color obtained from color palette.
-     */
-    public void setClockColor(int dark, int light) {
-        mHourPaint.setColor(dark);
-        invalidate();
-    }
-
-    private void init() {
-        mHourPaint.setColor(DEFAULT_COLOR);
-        mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
-        mHourPaint.setAntiAlias(true);
-        mHourPaint.setStrokeCap(Paint.Cap.ROUND);
-
-        mMinutePaint.setColor(Color.WHITE);
-        mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
-        mMinutePaint.setAntiAlias(true);
-        mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        final float centerX = getWidth() / 2f;
-        final float centerY = getHeight() / 2f;
-
-        final float minutesRotation = mTime.get(Calendar.MINUTE) * 6f;
-        final float hoursRotation = mTime.get(Calendar.HOUR) * 30
-                + mTime.get(Calendar.MINUTE) * 0.5f;
-
-        // Compute length of clock hands. Hour hand is 60% the length from center to edge
-        // and minute hand is twice the length to make sure it extends past screen edge.
-        double sMinuteHandLengthFactor = Math.sin(2d * Math.PI * minutesRotation / 360d);
-        float sMinuteHandLength = (float) (2d * (centerY + (centerX - centerY)
-                * sMinuteHandLengthFactor * sMinuteHandLengthFactor));
-        double sHourHandLengthFactor = Math.sin(2d * Math.PI * hoursRotation / 360d);
-        float sHourHandLength = (float) (0.6d * (centerY + (centerX - centerY)
-                * sHourHandLengthFactor * sHourHandLengthFactor));
-
-        canvas.save();
-
-        canvas.rotate(minutesRotation, centerX, centerY);
-        canvas.drawLine(
-                centerX,
-                centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
-                centerX,
-                centerY - sMinuteHandLength,
-                mMinutePaint);
-
-        canvas.rotate(hoursRotation - minutesRotation, centerX, centerY);
-        canvas.drawLine(
-                centerX,
-                centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
-                centerX,
-                centerY - sHourHandLength,
-                mHourPaint);
-
-        canvas.restore();
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
-        onTimeChanged();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 665df77..0332477 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -16,47 +16,65 @@
 package com.android.systemui.bubbles;
 
 
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
+import java.util.Objects;
+
 /**
  * Encapsulates the data and UI elements of a bubble.
  */
 class Bubble {
 
+    private static final boolean DEBUG = false;
+    private static final String TAG = "Bubble";
+
     private final String mKey;
+    private final String mGroupId;
     private final BubbleExpandedView.OnBubbleBlockedListener mListener;
 
     private boolean mInflated;
-
-    public BubbleView iconView;
-    public BubbleExpandedView expandedView;
     public NotificationEntry entry;
+    BubbleView iconView;
+    BubbleExpandedView expandedView;
+
+    private static String groupId(NotificationEntry entry) {
+        UserHandle user = entry.notification.getUser();
+        return user.getIdentifier() + '|' + entry.notification.getPackageName();
+    }
 
     Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) {
         entry = e;
         mKey = e.key;
+        mGroupId = groupId(e);
         mListener = listener;
     }
 
-    /** @deprecated use the other constructor to defer View creation. */
-    @Deprecated
-    Bubble(NotificationEntry e, LayoutInflater inflater, BubbleStackView stackView,
-            BubbleExpandedView.OnBubbleBlockedListener listener) {
-        this(e, listener);
-        inflate(inflater, stackView);
-    }
-
     public String getKey() {
         return mKey;
     }
 
+    public String getGroupId() {
+        return mGroupId;
+    }
+
+    public String getPackageName() {
+        return entry.notification.getPackageName();
+    }
+
     boolean isInflated() {
         return mInflated;
     }
 
+    public void updateDotVisibility() {
+        if (iconView != null) {
+            iconView.updateDotVisibility();
+        }
+    }
+
     void inflate(LayoutInflater inflater, BubbleStackView stackView) {
         if (mInflated) {
             return;
@@ -73,10 +91,32 @@
         mInflated = true;
     }
 
+    void setDismissed() {
+        entry.setBubbleDismissed(true);
+        // TODO: move this somewhere where it can be guaranteed not to run until safe from flicker
+        if (expandedView != null) {
+            expandedView.cleanUpExpandedState();
+        }
+    }
+
     void setEntry(NotificationEntry entry) {
+        this.entry = entry;
         if (mInflated) {
             iconView.update(entry);
             expandedView.update(entry);
         }
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Bubble)) return false;
+        Bubble bubble = (Bubble) o;
+        return Objects.equals(mKey, bubble.mKey);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mKey);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 0fcc950..acdcfb2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -77,8 +77,7 @@
  * The controller manages addition, removal, and visible state of bubbles on screen.
  */
 @Singleton
-public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener,
-        ConfigurationController.ConfigurationListener {
+public class BubbleController implements ConfigurationController.ConfigurationListener {
 
     private static final String TAG = "BubbleController";
 
@@ -174,6 +173,10 @@
         @Override
         public void onStateChanged(int newState) {
             mState = newState;
+            boolean shouldCollapse = (mState != SHADE);
+            if (shouldCollapse) {
+                collapseStack();
+            }
             updateVisibility();
         }
     }
@@ -236,7 +239,6 @@
             if (mExpandListener != null) {
                 mStackView.setExpandListener(mExpandListener);
             }
-            mStackView.setOnBlockedListener(this);
         }
     }
 
@@ -284,28 +286,38 @@
         if (mStackView == null) {
             return false;
         }
-        for (Bubble bubble : mBubbleData.getBubbles()) {
-            if (!bubble.entry.isBubbleDismissed()) {
-                return true;
-            }
-        }
-        return false;
+        return mBubbleData.hasBubbles();
     }
 
     /**
      * Whether the stack of bubbles is expanded or not.
      */
     public boolean isStackExpanded() {
-        return mStackView != null && mStackView.isExpanded();
+        return mBubbleData.isExpanded();
+    }
+
+    /**
+     * Tell the stack of bubbles to expand.
+     */
+    public void expandStack() {
+        mBubbleData.setExpanded(true);
     }
 
     /**
      * Tell the stack of bubbles to collapse.
      */
     public void collapseStack() {
-        if (mStackView != null) {
-            mStackView.collapseStack();
-        }
+        mBubbleData.setExpanded(false /* expanded */);
+    }
+
+    void selectBubble(Bubble bubble) {
+        mBubbleData.setSelectedBubble(bubble);
+    }
+
+    @VisibleForTesting
+    void selectBubble(String key) {
+        Bubble bubble = mBubbleData.getBubbleWithKey(key);
+        selectBubble(bubble);
     }
 
     /**
@@ -314,8 +326,10 @@
      * @param notificationKey the notification key for the bubble to be selected
      */
     public void expandStackAndSelectBubble(String notificationKey) {
-        if (mStackView != null && mBubbleData.getBubble(notificationKey) != null) {
-            mStackView.setExpandedBubble(notificationKey);
+        Bubble bubble = mBubbleData.getBubbleWithKey(notificationKey);
+        if (bubble != null) {
+            mBubbleData.setSelectedBubble(bubble);
+            mBubbleData.setExpanded(true);
         }
     }
 
@@ -323,13 +337,7 @@
      * Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
      */
     void dismissStack(@DismissReason int reason) {
-        if (mStackView == null) {
-            return;
-        }
-        mStackView.stackDismissed(reason);
-
-        updateVisibility();
-        mNotificationEntryManager.updateNotifications();
+        mBubbleData.dismissAll(reason);
     }
 
     /**
@@ -348,20 +356,7 @@
      * @param notif the notification associated with this bubble.
      */
     void updateBubble(NotificationEntry notif) {
-        if (mStackView != null && mBubbleData.getBubble(notif.key) != null) {
-            // It's an update
-            mStackView.updateBubble(notif);
-        } else {
-            // It's new
-            ensureStackViewCreated();
-            mStackView.addBubble(notif);
-        }
-        Bubble bubble = mBubbleData.getBubble(notif.key);
-        if (shouldAutoExpand(notif)) {
-            mStackView.setSelectedBubble(bubble);
-            mStackView.setExpanded(true);
-        }
-        updateVisibility();
+        mBubbleData.notificationEntryUpdated(notif);
     }
 
     /**
@@ -371,23 +366,10 @@
      */
     @MainThread
     void removeBubble(String key, int reason) {
-        if (mStackView != null) {
-            mStackView.removeBubble(key, reason);
-        }
-        mNotificationEntryManager.updateNotifications();
-        updateVisibility();
-    }
-
-    @Override
-    public void onBubbleBlocked(NotificationEntry entry) {
-        Object[] bubbles = mBubbleData.getBubbles().toArray();
-        for (int i = 0; i < bubbles.length; i++) {
-            NotificationEntry e = ((Bubble) bubbles[i]).entry;
-            boolean samePackage = entry.notification.getPackageName().equals(
-                    e.notification.getPackageName());
-            if (samePackage) {
-                removeBubble(entry.key, DISMISS_BLOCKED);
-            }
+        // TEMP: refactor to change this to pass entry
+        Bubble bubble = mBubbleData.getBubbleWithKey(key);
+        if (bubble != null) {
+            mBubbleData.notificationEntryRemoved(bubble.entry, reason);
         }
     }
 
@@ -424,7 +406,6 @@
                 updateShowInShadeForSuppressNotification(entry);
                 entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
                 updateBubble(entry);
-                mStackView.updateDotVisibility(entry.key);
             }
         }
 
@@ -446,44 +427,57 @@
         }
     };
 
+    @SuppressWarnings("FieldCanBeLocal")
     private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
+
         @Override
         public void onBubbleAdded(Bubble bubble) {
-
+            ensureStackViewCreated();
+            mStackView.addBubble(bubble);
         }
 
         @Override
         public void onBubbleRemoved(Bubble bubble, int reason) {
-
+            if (mStackView != null) {
+                mStackView.removeBubble(bubble);
+            }
         }
 
         public void onBubbleUpdated(Bubble bubble) {
-
+            if (mStackView != null) {
+                mStackView.updateBubble(bubble);
+            }
         }
 
         @Override
         public void onOrderChanged(List<Bubble> bubbles) {
-
         }
 
         @Override
         public void onSelectionChanged(Bubble selectedBubble) {
-
+            if (mStackView != null) {
+                mStackView.setSelectedBubble(selectedBubble);
+            }
         }
 
         @Override
         public void onExpandedChanged(boolean expanded) {
-
+            if (mStackView != null) {
+                mStackView.setExpanded(expanded);
+            }
         }
 
         @Override
         public void showFlyoutText(Bubble bubble, String text) {
-
+            if (mStackView != null) {
+                mStackView.animateInFlyoutForBubble(bubble);
+            }
         }
 
         @Override
         public void apply() {
-
+            mNotificationEntryManager.updateNotifications();
+            updateVisibility();
         }
     };
 
@@ -514,7 +508,6 @@
             mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
         } else if (mStackView != null) {
             mStackView.setVisibility(INVISIBLE);
-            collapseStack();
         }
         updateBubblesShowing();
     }
@@ -621,14 +614,14 @@
         @Override
         public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
             if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
-                mStackView.collapseStack();
+                mBubbleData.setExpanded(false);
             }
         }
 
         @Override
         public void onActivityLaunchOnSecondaryDisplayRerouted() {
             if (mStackView != null) {
-                mStackView.collapseStack();
+                mBubbleData.setExpanded(false);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index fe3f9d1..259665d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -15,14 +15,24 @@
  */
 package com.android.systemui.bubbles;
 
-import androidx.annotation.Nullable;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
+
+import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.bubbles.BubbleController.DismissReason;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -33,6 +43,8 @@
 @Singleton
 public class BubbleData {
 
+    private static final String TAG = "BubbleData";
+
     /**
      * This interface reports changes to the state and appearance of bubbles which should be applied
      * as necessary to the UI.
@@ -53,7 +65,7 @@
          * A Bubble has been removed. A call to {@link #onOrderChanged(List)} will
          * follow.
          */
-        void onBubbleRemoved(Bubble bubble, @BubbleController.DismissReason int reason);
+        void onBubbleRemoved(Bubble bubble, @DismissReason int reason);
 
         /**
          * An existing bubble has been updated.
@@ -86,46 +98,253 @@
         void apply();
     }
 
-    private HashMap<String, Bubble> mBubbles = new HashMap<>();
+    private final Context mContext;
+    private final List<Bubble> mBubbles = new ArrayList<>();
+    private Bubble mSelectedBubble;
+    private boolean mExpanded;
     private Listener mListener;
 
     @VisibleForTesting
     @Inject
-    public BubbleData() {}
-
-    /**
-     * The set of bubbles.
-     */
-    public Collection<Bubble> getBubbles() {
-        return mBubbles.values();
+    public BubbleData(Context context) {
+        mContext = context;
     }
 
-    @Nullable
-    public Bubble getBubble(String key) {
-        return mBubbles.get(key);
+    public boolean hasBubbles() {
+        return !mBubbles.isEmpty();
     }
 
-    public void addBubble(Bubble b) {
-        mBubbles.put(b.getKey(), b);
+    public boolean isExpanded() {
+        return mExpanded;
     }
 
-    @Nullable
-    public Bubble removeBubble(String key) {
-        return mBubbles.remove(key);
+    public boolean hasBubbleWithKey(String key) {
+        return getBubbleWithKey(key) != null;
     }
 
-    public void updateBubble(String key, NotificationEntry newEntry) {
-        Bubble oldBubble = mBubbles.get(key);
-        if (oldBubble != null) {
-            oldBubble.setEntry(newEntry);
+    public void setExpanded(boolean expanded) {
+        if (setExpandedInternal(expanded)) {
+            mListener.apply();
         }
     }
 
-    public void clear() {
-        mBubbles.clear();
+    public void setSelectedBubble(Bubble bubble) {
+        if (setSelectedBubbleInternal(bubble)) {
+            mListener.apply();
+        }
+    }
+
+    public void notificationEntryUpdated(NotificationEntry entry) {
+        Bubble bubble = getBubbleWithKey(entry.key);
+        if (bubble == null) {
+            // Create a new bubble
+            bubble = new Bubble(entry, this::onBubbleBlocked);
+            mBubbles.add(0, bubble); // TODO: reorder/group
+            mListener.onBubbleAdded(bubble);
+        } else {
+            // Updates an existing bubble
+            bubble.setEntry(entry);
+            mListener.onBubbleUpdated(bubble);
+        }
+        if (shouldAutoExpand(entry)) {
+            setSelectedBubbleInternal(bubble);
+            if (!mExpanded) {
+                setExpandedInternal(true);
+            }
+        } else if (mSelectedBubble == null) {
+            setSelectedBubbleInternal(bubble);
+        }
+        // TODO: reorder/group
+        mListener.apply();
+    }
+
+    public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
+        int indexToRemove = indexForKey(entry.key);
+        if (indexToRemove >= 0) {
+            Bubble removed = mBubbles.remove(indexToRemove);
+            removed.setDismissed();
+            mListener.onBubbleRemoved(removed, reason);
+            maybeSendDeleteIntent(reason, removed.entry);
+
+            if (mBubbles.isEmpty()) {
+                setExpandedInternal(false);
+                setSelectedBubbleInternal(null);
+            } else if (removed == mSelectedBubble) {
+                int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
+                Bubble newSelected = mBubbles.get(newIndex);
+                setSelectedBubbleInternal(newSelected);
+            }
+            // TODO: reorder/group
+            mListener.apply();
+        }
+    }
+
+    public void dismissAll(@DismissReason int reason) {
+        boolean changed = setExpandedInternal(false);
+        while (!mBubbles.isEmpty()) {
+            Bubble bubble = mBubbles.remove(0);
+            bubble.setDismissed();
+            maybeSendDeleteIntent(reason, bubble.entry);
+            mListener.onBubbleRemoved(bubble, reason);
+            changed = true;
+        }
+        if (setSelectedBubbleInternal(null)) {
+            changed = true;
+        }
+        if (changed) {
+            // TODO: reorder/group
+            mListener.apply();
+        }
+    }
+
+    /**
+     * Requests a change to the selected bubble. Calls {@link Listener#onSelectionChanged} if
+     * the value changes.
+     *
+     * @param bubble the new selected bubble
+     * @return true if the state changed as a result
+     */
+    private boolean setSelectedBubbleInternal(Bubble bubble) {
+        if (Objects.equals(bubble, mSelectedBubble)) {
+            return false;
+        }
+        if (bubble != null && !mBubbles.contains(bubble)) {
+            Log.e(TAG, "Cannot select bubble which doesn't exist!"
+                    + " (" + bubble + ") bubbles=" + mBubbles);
+            return false;
+        }
+        if (mExpanded) {
+            // TODO: bubble.markAsActive() ?
+            bubble.entry.setShowInShadeWhenBubble(false);
+        }
+        mSelectedBubble = bubble;
+        mListener.onSelectionChanged(mSelectedBubble);
+        return true;
+    }
+
+
+    /**
+     * Requests a change to the expanded state. Calls {@link Listener#onExpandedChanged} if
+     * the value changes.
+     *
+     * @param shouldExpand the new requested state
+     * @return true if the state changed as a result
+     */
+    private boolean setExpandedInternal(boolean shouldExpand) {
+        if (mExpanded == shouldExpand) {
+            return false;
+        }
+        if (shouldExpand) {
+            if (mBubbles.isEmpty()) {
+                Log.e(TAG, "Attempt to expand stack when empty!");
+                return false;
+            }
+            if (mSelectedBubble == null) {
+                Log.e(TAG, "Attempt to expand stack without selected bubble!");
+                return false;
+            }
+            // TODO: bubble.markAsActive() ?
+            mSelectedBubble.entry.setShowInShadeWhenBubble(false);
+        }
+        // TODO: reorder/regroup
+        mExpanded = shouldExpand;
+        mListener.onExpandedChanged(mExpanded);
+        return true;
+    }
+
+    private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
+        if (reason == BubbleController.DISMISS_USER_GESTURE) {
+            Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
+            PendingIntent deleteIntent = bubbleMetadata != null
+                    ? bubbleMetadata.getDeleteIntent()
+                    : null;
+            if (deleteIntent != null) {
+                try {
+                    deleteIntent.send();
+                } catch (PendingIntent.CanceledException e) {
+                    Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
+                }
+            }
+        }
+    }
+
+    private void onBubbleBlocked(NotificationEntry entry) {
+        boolean changed = false;
+        final String blockedPackage = entry.notification.getPackageName();
+        for (Iterator<Bubble> i = mBubbles.iterator(); i.hasNext(); ) {
+            Bubble bubble = i.next();
+            if (bubble.getPackageName().equals(blockedPackage)) {
+                i.remove();
+                mListener.onBubbleRemoved(bubble, BubbleController.DISMISS_BLOCKED);
+                changed = true;
+            }
+        }
+        if (changed) {
+            // TODO: reorder/group
+            mListener.apply();
+        }
+    }
+
+    private int indexForKey(String key) {
+        for (int i = 0; i < mBubbles.size(); i++) {
+            Bubble bubble = mBubbles.get(i);
+            if (bubble.getKey().equals(key)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private Bubble removeBubbleWithKey(String key) {
+        for (int i = 0; i < mBubbles.size(); i++) {
+            Bubble bubble = mBubbles.get(i);
+            if (bubble.getKey().equals(key)) {
+                mBubbles.remove(i);
+                return bubble;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * The set of bubbles.
+     *
+     * @deprecated
+     */
+    @Deprecated
+    public Collection<Bubble> getBubbles() {
+        return Collections.unmodifiableList(mBubbles);
+    }
+
+    @VisibleForTesting(visibility = PRIVATE)
+    Bubble getBubbleWithKey(String key) {
+        for (int i = 0; i < mBubbles.size(); i++) {
+            Bubble bubble = mBubbles.get(i);
+            if (bubble.getKey().equals(key)) {
+                return bubble;
+            }
+        }
+        return null;
     }
 
     public void setListener(Listener listener) {
         mListener = listener;
     }
-}
+
+    boolean shouldAutoExpand(NotificationEntry entry) {
+        Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
+        return metadata != null && metadata.getAutoExpandBubble()
+                && isForegroundApp(entry.notification.getPackageName());
+    }
+
+    /**
+     * Return true if the applications with the package name is running in foreground.
+     *
+     * @param pkgName application package name.
+     */
+    boolean isForegroundApp(String pkgName) {
+        ActivityManager am = mContext.getSystemService(ActivityManager.class);
+        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1 /* maxNum */);
+        return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 424cd55..18b2e37 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -20,8 +20,6 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
 import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.PendingIntent;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Outline;
@@ -54,9 +52,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.ViewClippingUtil;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.bubbles.BubbleController.DismissReason;
 import com.android.systemui.bubbles.animation.ExpandedAnimationController;
 import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
 import com.android.systemui.bubbles.animation.StackAnimationController;
@@ -359,14 +355,13 @@
         }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_DISMISS:
-                Dependency.get(BubbleController.class).dismissStack(
-                        BubbleController.DISMISS_ACCESSIBILITY_ACTION);
+                mBubbleData.dismissAll(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
                 return true;
             case AccessibilityNodeInfo.ACTION_COLLAPSE:
-                collapseStack();
+                mBubbleData.setExpanded(false);
                 return true;
             case AccessibilityNodeInfo.ACTION_EXPAND:
-                expandStack();
+                mBubbleData.setExpanded(true);
                 return true;
         }
         return false;
@@ -393,9 +388,9 @@
      * @param key the {@link NotificationEntry#key} associated with the bubble.
      */
     public void updateDotVisibility(String key) {
-        Bubble b = mBubbleData.getBubble(key);
+        Bubble b = mBubbleData.getBubbleWithKey(key);
         if (b != null) {
-            b.iconView.updateDotVisibility();
+            b.updateDotVisibility();
         }
     }
 
@@ -407,16 +402,6 @@
     }
 
     /**
-     * Sets the listener to notify when a bubble is blocked.
-     */
-    public void setOnBlockedListener(BubbleExpandedView.OnBubbleBlockedListener listener) {
-        mBlockedListener = listener;
-        for (Bubble b : mBubbleData.getBubbles()) {
-            b.expandedView.setOnBlockedListener(mBlockedListener);
-        }
-    }
-
-    /**
      * Whether the stack of bubbles is expanded or not.
      */
     public boolean isExpanded() {
@@ -445,7 +430,7 @@
      */
     @Deprecated
     void setExpandedBubble(String key) {
-        Bubble bubbleToExpand = mBubbleData.getBubble(key);
+        Bubble bubbleToExpand = mBubbleData.getBubbleWithKey(key);
         if (bubbleToExpand != null) {
             setSelectedBubble(bubbleToExpand);
             bubbleToExpand.entry.setShowInShadeWhenBubble(false);
@@ -466,11 +451,36 @@
         }
     }
 
+    // via BubbleData.Listener
+    void addBubble(Bubble bubble) {
+        bubble.inflate(mInflater, this);
+        mBubbleContainer.addView(bubble.iconView, 0,
+                new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
+        ViewClippingUtil.setClippingDeactivated(bubble.iconView, true, mClippingParameters);
+        requestUpdate();
+        logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
+    }
+
+    // via BubbleData.Listener
+    void removeBubble(Bubble bubble) {
+        // Remove it from the views
+        int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
+        mBubbleContainer.removeViewAt(removedIndex);
+        logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
+    }
+
+    // via BubbleData.Listener
+    void updateBubble(Bubble bubble) {
+        requestUpdate();
+        logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
+    }
+
     /**
      * Changes the currently selected bubble. If the stack is already expanded, the newly selected
      * bubble will be shown immediately. This does not change the expanded state or change the
      * position of any bubble.
      */
+    // via BubbleData.Listener
     public void setSelectedBubble(Bubble bubbleToSelect) {
         if (mExpandedBubble != null && mExpandedBubble.equals(bubbleToSelect)) {
             return;
@@ -489,7 +499,8 @@
                 logBubbleEvent(previouslySelected, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
                 logBubbleEvent(bubbleToSelect, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
                 notifyExpansionChanged(previouslySelected.entry, false /* expanded */);
-                notifyExpansionChanged(bubbleToSelect.entry, true /* expanded */);
+                notifyExpansionChanged(bubbleToSelect == null ? null : bubbleToSelect.entry,
+                        true /* expanded */);
             });
         }
     }
@@ -497,13 +508,15 @@
     /**
      * Changes the expanded state of the stack.
      *
-     * @param expanded whether the bubble stack should appear expanded
+     * @param shouldExpand whether the bubble stack should appear expanded
      */
-    public void setExpanded(boolean expanded) {
-        if (expanded == mIsExpanded) {
+    // via BubbleData.Listener
+    public void setExpanded(boolean shouldExpand) {
+        boolean wasExpanded = mIsExpanded;
+        if (shouldExpand == wasExpanded) {
             return;
         }
-        if (mIsExpanded) {
+        if (wasExpanded) {
             // Collapse the stack
             animateExpansion(false /* expand */);
             logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
@@ -518,131 +531,17 @@
     }
 
     /**
-     * Adds a bubble to the top of the stack.
-     *
-     * @param entry the notification to add to the stack of bubbles.
-     */
-    void addBubble(NotificationEntry entry) {
-        Bubble b = new Bubble(entry, mInflater, this /* stackView */, mBlockedListener);
-        mBubbleData.addBubble(b);
-
-        mBubbleContainer.addView(b.iconView, 0,
-                new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
-        ViewClippingUtil.setClippingDeactivated(b.iconView, true, mClippingParameters);
-
-        requestUpdate();
-        logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
-
-        animateInFlyoutForBubble(b);
-    }
-
-    /**
-     * Remove a bubble from the stack.
-     */
-    void removeBubble(String key, int reason) {
-        Bubble b = mBubbleData.removeBubble(key);
-        if (b == null) {
-            return;
-        }
-        setBubbleDismissed(b, reason);
-
-        // Remove it from the views
-        int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
-        mBubbleContainer.removeViewAt(removedIndex);
-
-        int bubbleCount = mBubbleContainer.getChildCount();
-        if (bubbleCount == 0) {
-            // If no bubbles remain, collapse the entire stack.
-            collapseStack();
-            return;
-        } else if (b.equals(mExpandedBubble)) {
-            // Was the current bubble just removed?
-            // If we have other bubbles and are expanded go to the next one or previous
-            // if the bubble removed was last
-            int nextIndex = bubbleCount > removedIndex ? removedIndex : bubbleCount - 1;
-            BubbleView expandedBubble = (BubbleView) mBubbleContainer.getChildAt(nextIndex);
-            if (mIsExpanded) {
-                setExpandedBubble(expandedBubble.getKey());
-            } else {
-                mExpandedBubble = null;
-            }
-        }
-        // TODO: consider logging reason code
-        logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
-    }
-
-    /**
      * Dismiss the stack of bubbles.
+     * @deprecated
      */
+    @Deprecated
     void stackDismissed(int reason) {
-        for (Bubble bubble : mBubbleData.getBubbles()) {
-            setBubbleDismissed(bubble, reason);
-        }
-        mBubbleData.clear();
-        collapseStack();
-        mBubbleContainer.removeAllViews();
-        mExpandedViewContainer.removeAllViews();
-        // TODO: consider logging reason code
+        mBubbleData.dismissAll(reason);
         logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
                 StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
     }
 
     /**
-     * Marks the notification entry as dismissed & calls any delete intents for the bubble.
-     *
-     * <p>Note: This does not remove the Bubble from BubbleData.
-     *
-     * @param bubble the Bubble being dismissed
-     * @param reason code for the reason the dismiss was triggered
-     * @see BubbleController.DismissReason
-     */
-    private void setBubbleDismissed(Bubble bubble, @DismissReason int reason) {
-        if (DEBUG) {
-            Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
-        }
-        bubble.entry.setBubbleDismissed(true);
-        bubble.expandedView.cleanUpExpandedState();
-
-        if (reason == BubbleController.DISMISS_USER_GESTURE) {
-            Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
-            PendingIntent deleteIntent = bubbleMetadata != null
-                    ? bubbleMetadata.getDeleteIntent()
-                    : null;
-            if (deleteIntent != null) {
-                try {
-                    deleteIntent.send();
-                } catch (PendingIntent.CanceledException e) {
-                    Log.w(TAG, "Failed to send delete intent for bubble with key: "
-                            + (bubble.entry != null ? bubble.entry.key : " null entry"));
-                }
-            }
-        }
-    }
-
-    /**
-     * Updates a bubble in the stack.
-     *  @param entry the entry to update in the stack.
-     */
-    public void updateBubble(NotificationEntry entry) {
-        Bubble b = mBubbleData.getBubble(entry.key);
-        mBubbleData.updateBubble(entry.key, entry);
-
-        if (!mIsExpanded) {
-            // If alerting it gets promoted to top of the stack.
-            if (mBubbleContainer.indexOfChild(b.iconView) != 0) {
-                mBubbleContainer.moveViewTo(b.iconView, 0);
-            }
-            requestUpdate();
-            animateInFlyoutForBubble(b /* bubble */);
-        }
-        if (mIsExpanded && entry.equals(mExpandedBubble.entry)) {
-            entry.setShowInShadeWhenBubble(false);
-            requestUpdate();
-        }
-        logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
-    }
-
-    /**
      * @return the view the touch event is on
      */
     @Nullable
@@ -670,7 +569,7 @@
         return this;
     }
 
-    public View getFlyoutView() {
+    View getFlyoutView() {
         return mFlyout;
     }
 
@@ -683,13 +582,8 @@
      */
     @Deprecated
     @MainThread
-    public void collapseStack() {
-        if (mIsExpanded) {
-            // TODO: Save opened bubble & move it to top of stack
-            animateExpansion(false /* shouldExpand */);
-            notifyExpansionChanged(mExpandedBubble.entry, mIsExpanded);
-            logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
-        }
+    void collapseStack() {
+        mBubbleData.setExpanded(false);
     }
 
     /**
@@ -712,12 +606,8 @@
      */
     @Deprecated
     @MainThread
-    public void expandStack() {
-        if (!mIsExpanded) {
-            String expandedBubbleKey = getBubbleAt(0).getKey();
-            setExpandedBubble(expandedBubbleKey);
-            logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED);
-        }
+    void expandStack() {
+        mBubbleData.setExpanded(true);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 6f50baa..4590470 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -25,9 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.Rect;
 import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
@@ -37,13 +35,8 @@
 import android.os.Trace;
 import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
 import android.text.TextUtils;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ImageSpan;
 import android.text.style.StyleSpan;
-import android.util.MathUtils;
 
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.slice.Slice;
@@ -205,9 +198,9 @@
                 addMediaLocked(builder);
             } else {
                 builder.addRow(new RowBuilder(mDateUri).setTitle(mLastText));
-                addNextAlarmLocked(builder);
-                addZenModeLocked(builder);
             }
+            addNextAlarmLocked(builder);
+            addZenModeLocked(builder);
             addPrimaryActionLocked(builder);
             slice = builder.build();
         }
@@ -221,32 +214,25 @@
 
     protected void addMediaLocked(ListBuilder listBuilder) {
         if (mMediaMetaData != null) {
-            SpannableStringBuilder builder = new SpannableStringBuilder();
-
-            Icon notificationIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
-            if (notificationIcon != null) {
-                Drawable drawable = notificationIcon.loadDrawable(getContext());
-                Rect mediaBounds = new Rect(0 /* left */, 0 /* top */,
-                        drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
-                int iconHeaderSize = getContext().getResources()
-                        .getDimensionPixelSize(R.dimen.header_icon_size);
-                MathUtils.fitRect(mediaBounds, iconHeaderSize);
-                drawable.setBounds(mediaBounds);
-                builder.append("# ");
-                builder.setSpan(new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_CENTER),
-                        0 /* start */, 1 /* end */, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-            }
-
             CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE);
             if (TextUtils.isEmpty(title)) {
                 title = getContext().getResources().getString(R.string.music_controls_no_title);
             }
-            builder.append(title);
-            listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(builder));
+            listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title));
 
             CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST);
             if (!TextUtils.isEmpty(album)) {
-                listBuilder.addRow(new RowBuilder(mMediaUri).setTitle(album));
+                RowBuilder albumBuilder = new RowBuilder(mMediaUri);
+                albumBuilder.setTitle(album);
+
+                Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
+                IconCompat mediaIconCompat = mediaIcon == null ? null
+                        : IconCompat.createFromIcon(getContext(), mediaIcon);
+                if (mediaIconCompat != null) {
+                    albumBuilder.addEndItem(mediaIconCompat, ListBuilder.ICON_IMAGE);
+                }
+
+                listBuilder.addRow(albumBuilder);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
index 0eeaa9b..7de8b74 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
@@ -139,43 +139,49 @@
 
     @Override
     public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) {
-        if (info.anySimReady) {
-            boolean[] slotSeen = new boolean[SIM_SLOTS];
-            if (info.listOfCarriers.length == info.subscriptionIds.length) {
-                for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) {
-                    int slot = getSlotIndex(info.subscriptionIds[i]);
-                    if (slot >= SIM_SLOTS) {
-                        Log.w(TAG, "updateInfoCarrier - slot: " + slot);
-                        continue;
+        if (info.airplaneMode) {
+            setVisibility(View.GONE);
+        } else {
+            setVisibility(View.VISIBLE);
+            if (info.anySimReady) {
+                boolean[] slotSeen = new boolean[SIM_SLOTS];
+                if (info.listOfCarriers.length == info.subscriptionIds.length) {
+                    for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) {
+                        int slot = getSlotIndex(info.subscriptionIds[i]);
+                        if (slot >= SIM_SLOTS) {
+                            Log.w(TAG, "updateInfoCarrier - slot: " + slot);
+                            continue;
+                        }
+                        if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+                            Log.e(TAG,
+                                    "Invalid SIM slot index for subscription: "
+                                            + info.subscriptionIds[i]);
+                            continue;
+                        }
+                        mInfos[slot].visible = true;
+                        slotSeen[slot] = true;
+                        mCarrierGroups[slot].setCarrierText(
+                                info.listOfCarriers[i].toString().trim());
+                        mCarrierGroups[slot].setVisibility(View.VISIBLE);
                     }
-                    if (slot == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-                        Log.e(TAG,
-                                "Invalid SIM slot index for subscription: "
-                                        + info.subscriptionIds[i]);
-                        continue;
+                    for (int i = 0; i < SIM_SLOTS; i++) {
+                        if (!slotSeen[i]) {
+                            mInfos[i].visible = false;
+                            mCarrierGroups[i].setVisibility(View.GONE);
+                        }
                     }
-                    mInfos[slot].visible = true;
-                    slotSeen[slot] = true;
-                    mCarrierGroups[slot].setCarrierText(info.listOfCarriers[i].toString().trim());
-                    mCarrierGroups[slot].setVisibility(View.VISIBLE);
-                }
-                for (int i = 0; i < SIM_SLOTS; i++) {
-                    if (!slotSeen[i]) {
-                        mInfos[i].visible = false;
-                        mCarrierGroups[i].setVisibility(View.GONE);
-                    }
+                } else {
+                    Log.e(TAG, "Carrier information arrays not of same length");
                 }
             } else {
-                Log.e(TAG, "Carrier information arrays not of same length");
-            }
-        } else {
-            mInfos[0].visible = false;
-            mCarrierGroups[0].setCarrierText(info.carrierText);
-            mCarrierGroups[0].setVisibility(View.VISIBLE);
-            for (int i = 1; i < SIM_SLOTS; i++) {
-                mInfos[i].visible = false;
-                mCarrierGroups[i].setCarrierText("");
-                mCarrierGroups[i].setVisibility(View.GONE);
+                mInfos[0].visible = false;
+                mCarrierGroups[0].setCarrierText(info.carrierText);
+                mCarrierGroups[0].setVisibility(View.VISIBLE);
+                for (int i = 1; i < SIM_SLOTS; i++) {
+                    mInfos[i].visible = false;
+                    mCarrierGroups[i].setCarrierText("");
+                    mCarrierGroups[i].setVisibility(View.GONE);
+                }
             }
         }
         handleUpdateState();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 91cd652..8a360ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -15,11 +15,10 @@
 package com.android.systemui.qs.tileimpl;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.service.quicksettings.Tile;
-import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -27,6 +26,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSIconView;
@@ -46,6 +46,8 @@
     private ViewGroup mLabelContainer;
     private View mExpandIndicator;
     private View mExpandSpace;
+    private ColorStateList mColorLabelDefault;
+    private ColorStateList mColorLabelUnavailable;
 
     public QSTileView(Context context, QSIconView icon) {
         this(context, icon, false);
@@ -62,6 +64,11 @@
         createLabel();
         setOrientation(VERTICAL);
         setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
+        mColorLabelDefault = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
+        // The text color for unavailable tiles is textColorSecondary, same as secondaryLabel for
+        // contrast purposes
+        mColorLabelUnavailable = Utils.getColorAttr(getContext(),
+                android.R.attr.textColorSecondary);
     }
 
     TextView getLabel() {
@@ -111,12 +118,8 @@
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
         if (!Objects.equals(mLabel.getText(), state.label) || mState != state.state) {
-            if (state.state == Tile.STATE_UNAVAILABLE) {
-                int color = QSTileImpl.getColorForState(getContext(), state.state);
-                state.label = new SpannableStringBuilder().append(state.label,
-                        new ForegroundColorSpan(color),
-                        SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
-            }
+            mLabel.setTextColor(state.state == Tile.STATE_UNAVAILABLE ? mColorLabelUnavailable
+                    : mColorLabelDefault);
             mState = state.state;
             mLabel.setText(state.label);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 72559f5..56dbe2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -608,6 +608,7 @@
         mConnectionCallbacks.add(listener);
         listener.onConnectionChanged(mOverviewProxy != null);
         listener.onInteractionFlagsChanged(mInteractionFlags);
+        listener.onBackButtonAlphaChanged(mBackButtonAlpha, false);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 907b3ad..85848ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -151,7 +151,7 @@
                     ? Dependency.get(AutoHideController.class)
                     : new AutoHideController(context, mHandler);
             navBar.setAutoHideController(autoHideController);
-            navBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+            navBar.restoreSystemUiVisibilityState();
             mNavigationBars.append(displayId, navBar);
 
             if (result != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 2e35f06..97f2dd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -22,7 +22,6 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 
 import com.android.systemui.R;
 import com.android.systemui.bubbles.BubbleData;
@@ -120,7 +119,7 @@
         for (int i = 0; i < N; i++) {
             NotificationEntry ent = activeNotifications.get(i);
             if (ent.isRowDismissed() || ent.isRowRemoved()
-                    || (mBubbleData.getBubble(ent.key) != null && !ent.showInShadeWhenBubble())) {
+                    || (mBubbleData.hasBubbleWithKey(ent.key) && !ent.showInShadeWhenBubble())) {
                 // we don't want to update removed notifications because they could
                 // temporarily become children if they were isolated before.
                 continue;
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 9eecdb9..4d2b56c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -123,6 +123,7 @@
     private static final boolean DEBUG = false;
     private static final String EXTRA_DISABLE_STATE = "disabled_state";
     private static final String EXTRA_DISABLE2_STATE = "disabled2_state";
+    private static final String EXTRA_SYSTEM_UI_VISIBILITY = "system_ui_visibility";
 
     /** Allow some time inbetween the long press for back and recents. */
     private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
@@ -156,7 +157,7 @@
     private Locale mLocale;
     private int mLayoutDirection;
 
-    private int mSystemUiVisibility;
+    private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
     private LightBarController mLightBarController;
     private AutoHideController mAutoHideController;
 
@@ -277,6 +278,7 @@
         if (savedInstanceState != null) {
             mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
             mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0);
+            mSystemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
         }
         mAccessibilityManagerWrapper.addCallback(mAccessibilityListener);
 
@@ -363,6 +365,7 @@
         super.onSaveInstanceState(outState);
         outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
         outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2);
+        outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, mSystemUiVisibility);
         if (mNavigationBarView != null) {
             mNavigationBarView.getLightTransitionsController().saveState(outState);
         }
@@ -492,13 +495,8 @@
         }
     }
 
-    /**
-     * Sets System UI flags to {@link NavigationBarFragment}.
-     *
-     * @see View#setSystemUiVisibility(int)
-     */
-    public void setSystemUiVisibility(int systemUiVisibility) {
-        mSystemUiVisibility = systemUiVisibility;
+    /** Restores the System UI flags saved state to {@link NavigationBarFragment}. */
+    public void restoreSystemUiVisibilityState() {
         final int barMode = computeBarMode(0, mSystemUiVisibility);
         if (barMode != -1) {
             mNavigationBarMode = barMode;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
index 45fc756..1862ed3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java
@@ -22,6 +22,9 @@
 import android.view.GestureDetector;
 import android.view.MotionEvent;
 
+import androidx.core.view.ViewCompat;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
+
 import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.R;
 
@@ -31,7 +34,7 @@
     private static final int[] OPTED_OUT_STATE = new int[] { R.attr.optedOut };
 
     private ConfirmedTapListener mConfirmedTapListener;
-    private boolean mComponentEnabled = false;
+    private boolean mCaptionsEnabled = false;
     private boolean mOptedOut = false;
 
     private GestureDetector mGestureDetector;
@@ -39,16 +42,14 @@
             new GestureDetector.SimpleOnGestureListener() {
         @Override
         public boolean onSingleTapConfirmed(MotionEvent e) {
-            if (mConfirmedTapListener != null) {
-                mConfirmedTapListener.onConfirmedTap();
-                return true;
-            }
-            return false;
+            return tryToSendTapConfirmedEvent();
         }
     };
 
     public CaptionsToggleImageButton(Context context, AttributeSet attrs) {
         super(context, attrs);
+        this.setContentDescription(
+                getContext().getString(R.string.volume_odi_captions_content_description));
     }
 
     @Override
@@ -66,16 +67,32 @@
         return state;
     }
 
-    Runnable setComponentEnabled(boolean isComponentEnabled) {
-        this.mComponentEnabled = isComponentEnabled;
+    Runnable setCaptionsEnabled(boolean areCaptionsEnabled) {
+        this.mCaptionsEnabled = areCaptionsEnabled;
 
-        return this.setImageResourceAsync(this.mComponentEnabled
+        ViewCompat.replaceAccessibilityAction(
+                this,
+                AccessibilityActionCompat.ACTION_CLICK,
+                mCaptionsEnabled
+                        ? getContext().getString(R.string.volume_odi_captions_hint_disable)
+                        : getContext().getString(R.string.volume_odi_captions_hint_enable),
+                (view, commandArguments) -> tryToSendTapConfirmedEvent());
+
+        return this.setImageResourceAsync(mCaptionsEnabled
                 ? R.drawable.ic_volume_odi_captions
                 : R.drawable.ic_volume_odi_captions_disabled);
     }
 
-    boolean getComponentEnabled() {
-        return this.mComponentEnabled;
+    private boolean tryToSendTapConfirmedEvent() {
+        if (mConfirmedTapListener != null) {
+            mConfirmedTapListener.onConfirmedTap();
+            return true;
+        }
+        return false;
+    }
+
+    boolean getCaptionsEnabled() {
+        return this.mCaptionsEnabled;
     }
 
     /** Sets whether or not the current stream has opted out of captions */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 5095370..8d9c5a3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -596,9 +596,9 @@
     }
 
     private void updateCaptionsIcon() {
-        boolean componentEnabled = mController.areCaptionsEnabled();
-        if (mODICaptionsIcon.getComponentEnabled() != componentEnabled) {
-            mHandler.post(mODICaptionsIcon.setComponentEnabled(componentEnabled));
+        boolean captionsEnabled = mController.areCaptionsEnabled();
+        if (mODICaptionsIcon.getCaptionsEnabled() != captionsEnabled) {
+            mHandler.post(mODICaptionsIcon.setCaptionsEnabled(captionsEnabled));
         }
 
         boolean isOptedOut = mController.isCaptionStreamOptedOut();
@@ -878,7 +878,6 @@
         }
 
         view.setContentDescription(mContext.getString(currStateResId));
-
         view.setAccessibilityDelegate(new AccessibilityDelegate() {
             public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
                 super.onInitializeAccessibilityNodeInfo(host, info);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 8e061cc..df534d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -37,6 +37,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -81,6 +82,8 @@
     private ConnectivityManager mConnectivityManager;
     @Mock
     private TelephonyManager mTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
     private CarrierTextController.CarrierTextCallbackInfo mCarrierTextCallbackInfo;
 
     private CarrierTextController mCarrierTextController;
@@ -94,6 +97,7 @@
         mContext.addMockSystemService(WifiManager.class, mWifiManager);
         mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
         mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
+        mContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
         mDependency.injectMockDependency(WakefulnessLifecycle.class);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(mTestableLooper.getLooper()));
@@ -169,6 +173,7 @@
         list.add(TEST_SUBSCRIPTION);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
         when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
         ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -192,6 +197,7 @@
         list.add(TEST_SUBSCRIPTION_ROAMING);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
         when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
         ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
similarity index 91%
rename from packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
rename to packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
index 26fa62b..4bb2395 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/AnalogClockControllerTest.java
@@ -38,9 +38,9 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
-public final class StretchAnalogClockControllerTest extends SysuiTestCase {
+public final class AnalogClockControllerTest extends SysuiTestCase {
 
-    private StretchAnalogClockController mClockController;
+    private AnalogClockController mClockController;
     @Mock SysuiColorExtractor mMockColorExtractor;
 
     @Before
@@ -49,7 +49,7 @@
 
         Resources res = getContext().getResources();
         LayoutInflater layoutInflater = LayoutInflater.from(getContext());
-        mClockController = new StretchAnalogClockController(res, layoutInflater,
+        mClockController = new AnalogClockController(res, layoutInflater,
                 mMockColorExtractor);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 20f539b..40a5357 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -146,7 +146,7 @@
         when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
         when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
 
-        mBubbleData = new BubbleData();
+        mBubbleData = new BubbleData(mContext);
         mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
                 mBubbleData, mConfigurationController);
         mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
@@ -177,25 +177,27 @@
     public void testRemoveBubble() {
         mBubbleController.updateBubble(mRow.getEntry());
         assertTrue(mBubbleController.hasBubbles());
-
+        verify(mNotificationEntryManager).updateNotifications();
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
 
         mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         assertTrue(mRow.getEntry().isBubbleDismissed());
-        verify(mNotificationEntryManager).updateNotifications();
+        verify(mNotificationEntryManager, times(2)).updateNotifications();
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
 
     @Test
     public void testDismissStack() {
         mBubbleController.updateBubble(mRow.getEntry());
+        verify(mNotificationEntryManager, times(1)).updateNotifications();
         mBubbleController.updateBubble(mRow2.getEntry());
+        verify(mNotificationEntryManager, times(2)).updateNotifications();
         assertTrue(mBubbleController.hasBubbles());
 
         mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
-        verify(mNotificationEntryManager).updateNotifications();
+        verify(mNotificationEntryManager, times(3)).updateNotifications();
         assertTrue(mRow.getEntry().isBubbleDismissed());
         assertTrue(mRow2.getEntry().isBubbleDismissed());
     }
@@ -215,7 +217,7 @@
 
         // Expand the stack
         BubbleStackView stackView = mBubbleController.getStackView();
-        stackView.expandStack();
+        mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
         verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
         assertTrue(mStatusBarWindowController.getBubbleExpanded());
@@ -224,7 +226,7 @@
         assertFalse(mRow.getEntry().showInShadeWhenBubble());
 
         // Collapse
-        stackView.collapseStack();
+        mBubbleController.collapseStack();
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
         assertFalse(mBubbleController.isStackExpanded());
         assertFalse(mStatusBarWindowController.getBubbleExpanded());
@@ -245,23 +247,24 @@
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
-        stackView.expandStack();
+        mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
-        // Last added is the one that is expanded
-        assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertFalse(mRow2.getEntry().showInShadeWhenBubble());
-
-        // Switch which bubble is expanded
-        stackView.setExpandedBubble(mRow.getEntry());
+        // First added is the one that is expanded
         assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
         assertFalse(mRow.getEntry().showInShadeWhenBubble());
 
+        // Switch which bubble is expanded
+        mBubbleController.selectBubble(mRow2.getEntry().key);
+        stackView.setExpandedBubble(mRow2.getEntry());
+        assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
+        assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+
         // collapse for previous bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
         // expand for selected bubble
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
 
         // Collapse
         mBubbleController.collapseStack();
@@ -280,7 +283,7 @@
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
-        stackView.expandStack();
+        mBubbleController.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
         verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
@@ -299,30 +302,30 @@
 
         // Expand
         BubbleStackView stackView = mBubbleController.getStackView();
-        stackView.expandStack();
+        mBubbleController.expandStack();
 
         assertTrue(mBubbleController.isStackExpanded());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
-        // Last added is the one that is expanded
-        assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        assertFalse(mRow2.getEntry().showInShadeWhenBubble());
+        // First added is the one that is expanded
+        assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
+        assertFalse(mRow.getEntry().showInShadeWhenBubble());
 
         // Dismiss currently expanded
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
 
         // Make sure next bubble is selected
-        assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
-        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
+        assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
+        verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
 
         // Dismiss that one
         mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
                 BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
-        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
+        verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
         assertFalse(mBubbleController.hasBubbles());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
index 801308f..da31134 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleStackViewTest.java
@@ -48,7 +48,7 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mStackView = new BubbleStackView(mContext, new BubbleData(), null);
+        mStackView = new BubbleStackView(mContext, new BubbleData(getContext()), null);
         mBubble.entry = mNotifEntry;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 63d42a7..c534de7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
 import android.content.ContentResolver;
@@ -102,6 +103,7 @@
     @Test
     public void onBindSlice_readsMedia() {
         MediaMetadata metadata = mock(MediaMetadata.class);
+        when(metadata.getText(any())).thenReturn("metadata");
         mProvider.onDozingChanged(true);
         mProvider.onMetadataChanged(metadata);
         mProvider.onBindSlice(mProvider.getUri());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 2172a12..3662c38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -98,7 +98,7 @@
         mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
                 mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
                 mock(StatusBarStateControllerImpl.class), mEntryManager,
-                () -> mShadeController, new BubbleData());
+                () -> mShadeController, new BubbleData(mContext));
         Dependency.get(InitController.class).executePostInitTasks();
         mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
index 46e3226..7b6a128 100644
--- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -111,6 +111,15 @@
 
     @Override
     public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+        // MotionEventInjector would cancel any injected gesture when any MotionEvent arrives.
+        // For user using an external device to control the pointer movement, it's almost
+        // impossible to perform the gestures. Any slightly unintended movement results in the
+        // cancellation of the gesture.
+        if ((event.isFromSource(InputDevice.SOURCE_MOUSE)
+                && event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
+                && mOpenGesturesInProgress.get(EVENT_SOURCE, false)) {
+            return;
+        }
         cancelAnyPendingInjectedEvents();
         sendMotionEventToNext(event, rawEvent, policyFlags);
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index fdc3567..a94d1dc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -806,6 +806,17 @@
             mAugmentedAutofillState.injectAugmentedAutofillInfo(options, userId, packageName);
             return options;
         }
+
+        @Override
+        public boolean isAugmentedAutofillServiceForUser(int callingUid, int userId) {
+            synchronized (mLock) {
+                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+                if (service != null) {
+                    return service.isAugmentedAutofillServiceForUserLocked(callingUid);
+                }
+            }
+            return false;
+        }
     }
 
     /**
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 4bd6fbd3..f1963b3 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -1165,6 +1165,11 @@
         return true;
     }
 
+    boolean isAugmentedAutofillServiceForUserLocked(int callingUid) {
+        return mRemoteAugmentedAutofillServiceInfo != null
+                && mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid == callingUid;
+    }
+
     /**
      * Sets which packages and activities can trigger augmented autofill.
      *
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 593bb2c4..35dfccf 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -23,22 +23,20 @@
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import android.annotation.Nullable;
-import android.app.AppGlobals;
 import android.app.backup.BackupTransport;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
 import com.android.server.backup.transport.TransportClient;
 
 import com.google.android.collect.Sets;
@@ -67,12 +65,13 @@
      * </ol>
      */
     public static boolean appIsEligibleForBackup(ApplicationInfo app, int userId) {
-        return appIsEligibleForBackup(app, AppGlobals.getPackageManager(), userId);
+        return appIsEligibleForBackup(
+                app, LocalServices.getService(PackageManagerInternal.class), userId);
     }
 
     @VisibleForTesting
-    static boolean appIsEligibleForBackup(ApplicationInfo app,
-        IPackageManager packageManager, int userId) {
+    static boolean appIsEligibleForBackup(
+            ApplicationInfo app, PackageManagerInternal packageManager, int userId) {
         // 1. their manifest states android:allowBackup="false"
         if ((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
             return false;
@@ -108,9 +107,9 @@
     /**
      * Returns whether an app is eligible for backup at runtime. That is, the app has to:
      * <ol>
-     *     <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, PackageManager)}
+     *     <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, int)}
      *     <li>Return false for {@link #appIsStopped(ApplicationInfo)}
-     *     <li>Return false for {@link #appIsDisabled(ApplicationInfo, PackageManager)}
+     *     <li>Return false for {@link #appIsDisabled(ApplicationInfo, int)}
      *     <li>Be eligible for the transport via
      *         {@link BackupTransport#isAppEligibleForBackup(PackageInfo, boolean)}
      * </ol>
@@ -149,19 +148,13 @@
 
     /** Avoid backups of 'disabled' apps. */
     static boolean appIsDisabled(ApplicationInfo app, int userId) {
-        return appIsDisabled(app, AppGlobals.getPackageManager(), userId);
+        return appIsDisabled(app, LocalServices.getService(PackageManagerInternal.class), userId);
     }
 
     @VisibleForTesting
-    static boolean appIsDisabled(ApplicationInfo app,
-        IPackageManager packageManager, int userId) {
-        int enabledSetting;
-        try {
-            enabledSetting = packageManager.getApplicationEnabledSetting(app.packageName, userId);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to get application enabled setting: " + e);
-            return false;
-        }
+    static boolean appIsDisabled(
+            ApplicationInfo app, PackageManagerInternal packageManager, int userId) {
+        int enabledSetting = packageManager.getApplicationEnabledState(app.packageName, userId);
 
         switch (enabledSetting) {
             case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 757c2dc..7f411d8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -60,8 +60,8 @@
 import android.view.contentcapture.ContentCaptureCondition;
 import android.view.contentcapture.ContentCaptureHelper;
 import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.DataRemovalRequest;
 import android.view.contentcapture.IContentCaptureManager;
-import android.view.contentcapture.UserDataRemovalRequest;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.infra.AbstractRemoteService;
@@ -583,14 +583,14 @@
         }
 
         @Override
-        public void removeUserData(@NonNull UserDataRemovalRequest request) {
+        public void removeData(@NonNull DataRemovalRequest request) {
             Preconditions.checkNotNull(request);
             assertCalledByPackageOwner(request.getPackageName());
 
             final int userId = UserHandle.getCallingUserId();
             synchronized (mLock) {
                 final ContentCapturePerUserService service = getServiceForUserLocked(userId);
-                service.removeUserDataLocked(request);
+                service.removeDataLocked(request);
             }
         }
 
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 5649526..b4a1f38 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -57,7 +57,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.contentcapture.ContentCaptureCondition;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.infra.WhitelistHelper;
@@ -343,12 +343,12 @@
     }
 
     @GuardedBy("mLock")
-    public void removeUserDataLocked(@NonNull UserDataRemovalRequest request) {
+    public void removeDataLocked(@NonNull DataRemovalRequest request) {
         if (!isEnabledLocked()) {
             return;
         }
         assertCallerLocked(request.getPackageName());
-        mRemoteService.onUserDataRemovalRequest(request);
+        mRemoteService.onDataRemovalRequest(request);
     }
 
     @GuardedBy("mLock")
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 3fa3fdf..2171033 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -29,7 +29,7 @@
 import android.service.contentcapture.SnapshotData;
 import android.util.Slog;
 import android.view.contentcapture.ContentCaptureContext;
-import android.view.contentcapture.UserDataRemovalRequest;
+import android.view.contentcapture.DataRemovalRequest;
 
 import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
 import com.android.internal.os.IResultReceiver;
@@ -120,10 +120,10 @@
     }
 
     /**
-     * Called by {@link ContentCaptureServerSession} to request removal of user data.
+     * Called by {@link ContentCaptureServerSession} to request removal of content capture data.
      */
-    public void onUserDataRemovalRequest(@NonNull UserDataRemovalRequest request) {
-        scheduleAsyncRequest((s) -> s.onUserDataRemovalRequest(request));
+    public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
+        scheduleAsyncRequest((s) -> s.onDataRemovalRequest(request));
     }
 
     /**
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 6018f00..5c5b477 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,11 +18,10 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
-import android.os.SystemProperties;
+
+import com.android.internal.os.RoSystemProperties;
 
 class BluetoothService extends SystemService {
-    private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
-
     private BluetoothManagerService mBluetoothManagerService;
     private boolean mInitialized = false;
 
@@ -48,7 +47,7 @@
             publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
                     mBluetoothManagerService);
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
-                !SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false)) {
+                !RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
             initialize();
         }
     }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 382fdec..82bba77 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3766,7 +3766,7 @@
                 return Zygote.MOUNT_EXTERNAL_NONE;
             }
             if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
-                return Zygote.MOUNT_EXTERNAL_NONE;
+                return Zygote.MOUNT_EXTERNAL_DEFAULT;
             }
 
             // Determine if caller is holding runtime permission
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index a08c829..588e05d 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -29,6 +29,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.TransactionTooLargeException;
@@ -380,8 +381,9 @@
                 userId = controller.mUserController.getCurrentOrTargetUserId();
             }
             // temporarily allow receivers and services to open activities from background if the
-            // PendingIntent.send() caller was foreground at the time of sendInner() call
-            final boolean allowTrampoline = uid != callingUid
+            // PendingIntent.send() caller was foreground at the time of sendInner() call, unless
+            // caller is SYSTEM_UID
+            final boolean allowTrampoline = uid != callingUid && callingUid != Process.SYSTEM_UID
                     && controller.mAtmInternal.isUidForeground(callingUid);
 
             // note: we on purpose don't pass in the information about the PendingIntent's creator,
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 3dbea0d..d7d4851 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -17,7 +17,6 @@
 package com.android.server.attention;
 
 import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
-import static android.provider.Settings.System.ADAPTIVE_SLEEP;
 import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCELLED;
 import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
 
@@ -47,7 +46,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
-import android.provider.Settings;
 import android.service.attention.AttentionService;
 import android.service.attention.AttentionService.AttentionFailureCodes;
 import android.service.attention.AttentionService.AttentionSuccessCodes;
@@ -60,6 +58,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
@@ -102,16 +101,25 @@
     private final Object mLock;
     @GuardedBy("mLock")
     private final SparseArray<UserState> mUserStates = new SparseArray<>();
-    private final AttentionHandler mAttentionHandler;
+    private AttentionHandler mAttentionHandler;
 
-    private ComponentName mComponentName;
+    @VisibleForTesting
+    ComponentName mComponentName;
 
     public AttentionManagerService(Context context) {
+        this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE),
+                new Object(), null);
+        mAttentionHandler = new AttentionHandler();
+    }
+
+    @VisibleForTesting
+    AttentionManagerService(Context context, PowerManager powerManager, Object lock,
+            AttentionHandler handler) {
         super(context);
         mContext = Preconditions.checkNotNull(context);
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mLock = new Object();
-        mAttentionHandler = new AttentionHandler();
+        mPowerManager = powerManager;
+        mLock = lock;
+        mAttentionHandler = handler;
     }
 
     @Override
@@ -149,7 +157,8 @@
         return isServiceEnabled() && isServiceAvailable();
     }
 
-    private boolean isServiceEnabled() {
+    @VisibleForTesting
+    protected boolean isServiceEnabled() {
         return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, SERVICE_ENABLED,
                 DEFAULT_SERVICE_ENABLED);
     }
@@ -163,7 +172,8 @@
      *
      * @return {@code true} if the framework was able to dispatch the request
      */
-    private boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
+    @VisibleForTesting
+    boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
         Preconditions.checkNotNull(callbackInternal);
 
         if (!isAttentionServiceSupported()) {
@@ -259,37 +269,24 @@
     }
 
     /** Cancels the specified attention check. */
-    private void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
+    @VisibleForTesting
+    void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
         synchronized (mLock) {
             final UserState userState = peekCurrentUserStateLocked();
             if (userState == null) {
                 return;
             }
-
             if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
                 Slog.e(LOG_TAG, "Cannot cancel a non-current request");
                 return;
             }
-
             cancel(userState);
         }
     }
 
-    /** Disables service dependants. */
-    private void disableSelf() {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            if (DEBUG) {
-                Slog.d(LOG_TAG, "Disabling self.");
-            }
-            Settings.System.putInt(mContext.getContentResolver(), ADAPTIVE_SLEEP, 0);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
     @GuardedBy("mLock")
-    private void freeIfInactiveLocked() {
+    @VisibleForTesting
+    protected void freeIfInactiveLocked() {
         // If we are called here, it means someone used the API again - reset the timer then.
         mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);
 
@@ -306,7 +303,8 @@
 
 
     @GuardedBy("mLock")
-    private UserState getOrCreateCurrentUserStateLocked() {
+    @VisibleForTesting
+    protected UserState getOrCreateCurrentUserStateLocked() {
         return getOrCreateUserStateLocked(ActivityManager.getCurrentUser());
     }
 
@@ -322,7 +320,8 @@
 
     @GuardedBy("mLock")
     @Nullable
-    private UserState peekCurrentUserStateLocked() {
+    @VisibleForTesting
+    protected UserState peekCurrentUserStateLocked() {
         return peekUserStateLocked(ActivityManager.getCurrentUser());
     }
 
@@ -418,11 +417,6 @@
         public void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
             AttentionManagerService.this.cancelAttentionCheck(callbackInternal);
         }
-
-        @Override
-        public void disableSelf() {
-            AttentionManagerService.this.disableSelf();
-        }
     }
 
     private static final class AttentionCheckCache {
@@ -438,7 +432,8 @@
         }
     }
 
-    private static final class AttentionCheck {
+    @VisibleForTesting
+    static final class AttentionCheck {
         private final AttentionCallbackInternal mCallbackInternal;
         private final IAttentionCallback mIAttentionCallback;
         private boolean mIsDispatched;
@@ -455,7 +450,8 @@
         }
     }
 
-    private static final class UserState {
+    @VisibleForTesting
+    protected static class UserState {
         final ComponentName mComponentName;
         final AttentionServiceConnection mConnection = new AttentionServiceConnection();
 
@@ -473,7 +469,7 @@
         final Context mContext;
         final Object mLock;
 
-        private UserState(int userId, Context context, Object lock, ComponentName componentName) {
+        UserState(int userId, Context context, Object lock, ComponentName componentName) {
             mUserId = userId;
             mContext = Preconditions.checkNotNull(context);
             mLock = Preconditions.checkNotNull(lock);
@@ -529,7 +525,7 @@
             }
         }
 
-        private final class AttentionServiceConnection implements ServiceConnection {
+        private class AttentionServiceConnection implements ServiceConnection {
             @Override
             public void onServiceConnected(ComponentName name, IBinder service) {
                 init(IAttentionService.Stub.asInterface(service));
@@ -564,7 +560,8 @@
         }
     }
 
-    private class AttentionHandler extends Handler {
+    @VisibleForTesting
+    protected class AttentionHandler extends Handler {
         private static final int CHECK_CONNECTION_EXPIRATION = 1;
         private static final int ATTENTION_CHECK_TIMEOUT = 2;
 
@@ -596,7 +593,8 @@
         }
     }
 
-    private void cancel(UserState userState) {
+    @VisibleForTesting
+    void cancel(UserState userState) {
         if (userState == null || userState.mCurrentAttentionCheck == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 258c325..d28482e 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -52,6 +52,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.autofill.AutofillManagerInternal;
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -159,6 +160,7 @@
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
     private final ContentCaptureManagerInternal mContentCaptureInternal;
+    private final AutofillManagerInternal mAutofillInternal;
     private final IBinder mPermissionOwner;
     private HostClipboardMonitor mHostClipboardMonitor = null;
     private Thread mHostMonitorThread = null;
@@ -179,6 +181,7 @@
         mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
         mContentCaptureInternal = LocalServices.getService(ContentCaptureManagerInternal.class);
+        mAutofillInternal = LocalServices.getService(AutofillManagerInternal.class);
         final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
         mPermissionOwner = permOwner;
         if (IS_EMULATOR) {
@@ -653,13 +656,18 @@
                 // Clipboard can only be read by applications with focus..
                 boolean allowed = mWm.isUidFocused(callingUid);
                 if (!allowed && mContentCaptureInternal != null) {
-                    // ...or the Intelligence Service
+                    // ...or the Content Capture Service
                     allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
                             userId);
                 }
+                if (!allowed && mAutofillInternal != null) {
+                    // ...or the Augmented Autofill Service
+                    allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(callingUid,
+                            userId);
+                }
                 if (!allowed) {
                     Slog.e(TAG, "Denying clipboard access to " + callingPackage
-                            + ", application is not in focus neither is the IntelligeService for "
+                            + ", application is not in focus neither is a system service for "
                             + "user " + userId);
                 }
                 return allowed;
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 948c690..a1a8e35 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -33,6 +33,7 @@
 import android.util.Pair;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.TrafficStatsConstants;
 
 import libcore.io.IoUtils;
 
@@ -381,7 +382,8 @@
         protected void setupSocket(
                 int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
                 throws ErrnoException, IOException {
-            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                    TrafficStatsConstants.TAG_SYSTEM_PROBE);
             try {
                 mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
             } finally {
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 1ac09ad..f6ce2dc 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -39,6 +39,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.TrafficStatsConstants;
 import com.android.net.IProxyCallback;
 import com.android.net.IProxyPortListener;
 import com.android.net.IProxyService;
@@ -111,7 +112,8 @@
             String file;
             final Uri pacUrl = mPacUrl;
             if (Uri.EMPTY.equals(pacUrl)) return;
-            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                    TrafficStatsConstants.TAG_SYSTEM_PAC);
             try {
                 file = get(pacUrl);
             } catch (IOException ioe) {
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index a2515c8..580150e 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1228,6 +1228,24 @@
         public boolean isUidAllowedOnDisplay(int displayId, int uid) {
             return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
         }
+
+        @BinderThread
+        @Override
+        public void setActive(int clientId, boolean active) {
+            synchronized (mPerUserData.mLock) {
+                final InputMethodClientInfo clientInfo =
+                        mPerUserData.getClientFromIdLocked(clientId);
+                if (clientInfo == null) {
+                    Slog.e(TAG, "Unknown clientId=" + clientId);
+                    return;
+                }
+                try {
+                    clientInfo.mClient.setActive(active, false /* fullscreen */);
+                } catch (RemoteException e) {
+                    return;
+                }
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java
index c012ee4..7dffcb4 100644
--- a/services/core/java/com/android/server/location/GpsXtraDownloader.java
+++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java
@@ -20,6 +20,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.util.TrafficStatsConstants;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -92,7 +94,8 @@
 
         // load balance our requests among the available servers
         while (result == null) {
-            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                    TrafficStatsConstants.TAG_SYSTEM_GPS);
             try {
                 result = doDownload(mXtraServers[mNextServerIndex]);
             } finally {
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index a5f2217..fdb499b 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -140,6 +140,7 @@
     private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
 
     // Used to notify System UI and Settings when remote volume was changed.
+    @GuardedBy("mLock")
     final RemoteCallbackList<IRemoteVolumeController> mRemoteVolumeControllers =
             new RemoteCallbackList<>();
 
@@ -287,17 +288,19 @@
         if (!session.isActive()) {
             return;
         }
-        int size = mRemoteVolumeControllers.beginBroadcast();
-        MediaSession.Token token = session.getSessionToken();
-        for (int i = size - 1; i >= 0; i--) {
-            try {
-                IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
-                cb.remoteVolumeChanged(token, flags);
-            } catch (Exception e) {
-                Log.w(TAG, "Error sending volume change.", e);
+        synchronized (mLock) {
+            int size = mRemoteVolumeControllers.beginBroadcast();
+            MediaSession.Token token = session.getSessionToken();
+            for (int i = size - 1; i >= 0; i--) {
+                try {
+                    IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+                    cb.remoteVolumeChanged(token, flags);
+                } catch (Exception e) {
+                    Log.w(TAG, "Error sending volume change.", e);
+                }
             }
+            mRemoteVolumeControllers.finishBroadcast();
         }
-        mRemoteVolumeControllers.finishBroadcast();
     }
 
     @Override
@@ -647,19 +650,21 @@
             return;
         }
 
-        int size = mRemoteVolumeControllers.beginBroadcast();
-        MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
-        MediaSession.Token token = record == null ? null : record.getSessionToken();
+        synchronized (mLock) {
+            int size = mRemoteVolumeControllers.beginBroadcast();
+            MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
+            MediaSession.Token token = record == null ? null : record.getSessionToken();
 
-        for (int i = size - 1; i >= 0; i--) {
-            try {
-                IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
-                cb.updateRemoteController(token);
-            } catch (Exception e) {
-                Log.w(TAG, "Error sending default remote volume.", e);
+            for (int i = size - 1; i >= 0; i--) {
+                try {
+                    IRemoteVolumeController cb = mRemoteVolumeControllers.getBroadcastItem(i);
+                    cb.updateRemoteController(token);
+                } catch (Exception e) {
+                    Log.w(TAG, "Error sending default remote volume.", e);
+                }
             }
+            mRemoteVolumeControllers.finishBroadcast();
         }
-        mRemoteVolumeControllers.finishBroadcast();
     }
 
     void pushSession2TokensChangedLocked(int userId) {
@@ -1676,11 +1681,13 @@
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
-            try {
-                enforceStatusBarServicePermission("listen for volume changes", pid, uid);
-                mRemoteVolumeControllers.register(rvc);
-            } finally {
-                Binder.restoreCallingIdentity(token);
+            synchronized (mLock) {
+                try {
+                    enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+                    mRemoteVolumeControllers.register(rvc);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
             }
         }
 
@@ -1689,11 +1696,13 @@
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
-            try {
-                enforceStatusBarServicePermission("listen for volume changes", pid, uid);
-                mRemoteVolumeControllers.unregister(rvc);
-            } finally {
-                Binder.restoreCallingIdentity(token);
+            synchronized (mLock) {
+                try {
+                    enforceStatusBarServicePermission("listen for volume changes", pid, uid);
+                    mRemoteVolumeControllers.unregister(rvc);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7f1b25ca..042ac8c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1689,6 +1689,9 @@
 
         mPreferencesHelper.lockChannelsForOEM(getContext().getResources().getStringArray(
                 com.android.internal.R.array.config_nonBlockableNotificationPackages));
+
+        mZenModeHelper.setPriorityOnlyDndExemptPackages(getContext().getResources().getStringArray(
+                com.android.internal.R.array.config_priorityOnlyDndExemptPackages));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 7e74cc2..1f5b99c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -80,6 +80,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -96,7 +97,7 @@
     private final Context mContext;
     private final H mHandler;
     private final SettingsObserver mSettingsObserver;
-    @VisibleForTesting protected final AppOpsManager mAppOps;
+    private final AppOpsManager mAppOps;
     @VisibleForTesting protected final NotificationManager mNotificationManager;
     @VisibleForTesting protected ZenModeConfig mDefaultConfig;
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
@@ -123,11 +124,13 @@
 
     @VisibleForTesting protected boolean mIsBootComplete;
 
+    private String[] mPriorityOnlyDndExemptPackages;
+
     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
         mContext = context;
         mHandler = new H(looper);
         addCallback(mMetrics);
-        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mAppOps = context.getSystemService(AppOpsManager.class);
         mNotificationManager =  context.getSystemService(NotificationManager.class);
 
         mDefaultConfig = readDefaultConfig(mContext.getResources());
@@ -214,6 +217,10 @@
         loadConfigForUser(user, "onUserUnlocked");
     }
 
+    void setPriorityOnlyDndExemptPackages(String[] packages) {
+        mPriorityOnlyDndExemptPackages = packages;
+    }
+
     private void loadConfigForUser(int user, String reason) {
         if (mUser == user || user < UserHandle.USER_SYSTEM) return;
         mUser = user;
@@ -994,53 +1001,47 @@
         for (int usage : AudioAttributes.SDK_USAGES) {
             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
-                applyRestrictions(false /*mute*/, usage);
+                applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
-                applyRestrictions(muteNotifications || muteEverything, usage);
+                applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
-                applyRestrictions(muteCalls || muteEverything, usage);
+                applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
-                applyRestrictions(muteAlarms || muteEverything, usage);
+                applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
-                applyRestrictions(muteMedia || muteEverything, usage);
+                applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
                 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
                     // normally DND will only restrict touch sounds, not haptic feedback/vibrations
-                    applyRestrictions(muteSystem || muteEverything, usage,
+                    applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
                             AppOpsManager.OP_PLAY_AUDIO);
-                    applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
+                    applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
                 } else {
-                    applyRestrictions(muteSystem || muteEverything, usage);
+                    applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
                 }
             } else {
-                applyRestrictions(muteEverything, usage);
+                applyRestrictions(zenPriorityOnly, muteEverything, usage);
             }
         }
     }
 
 
     @VisibleForTesting
-    protected void applyRestrictions(boolean mute, int usage, int code) {
-        final String[] exceptionPackages = null; // none (for now)
-
-        // Only do this if we are executing within the system process...  otherwise
-        // we are running as test code, so don't have access to the protected call.
-        if (Process.myUid() == Process.SYSTEM_UID) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mAppOps.setRestriction(code, usage,
-                        mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                        exceptionPackages);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+    protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            mAppOps.setRestriction(code, usage,
+                    mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                    zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
     @VisibleForTesting
-    protected void applyRestrictions(boolean mute, int usage) {
-        applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
-        applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
+    protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
+        applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
+        applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
     }
 
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7b418b5..77e7df8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2801,6 +2801,11 @@
                         if (disabledPs.codePath == null || !disabledPs.codePath.exists()
                                 || disabledPs.pkg == null) {
                             possiblyDeletedUpdatedSystemApps.add(ps.name);
+                        } else {
+                            // We're expecting that the system app should remain disabled, but add
+                            // it to expecting better to recover in case the data version cannot
+                            // be scanned.
+                            mExpectingBetter.put(disabledPs.name, disabledPs.codePath);
                         }
                     }
                 }
@@ -9334,6 +9339,7 @@
                 | SCAN_UPDATE_SIGNATURE, currentTime, user);
         if (scanResult.success) {
             synchronized (mPackages) {
+                boolean appIdCreated = false;
                 try {
                     final String pkgName = scanResult.pkgSetting.name;
                     final Map<String, ReconciledPackage> reconcileResult = reconcilePackagesLocked(
@@ -9346,11 +9352,12 @@
                                     Collections.singletonMap(pkgName,
                                             getSharedLibLatestVersionSetting(scanResult))),
                             mSettings.mKeySetManagerService);
-                    prepareScanResultLocked(scanResult);
-                    commitReconciledScanResultLocked(
-                            reconcileResult.get(pkgName));
+                    appIdCreated = optimisticallyRegisterAppId(scanResult);
+                    commitReconciledScanResultLocked(reconcileResult.get(pkgName));
                 } catch (PackageManagerException e) {
-                    unprepareScanResultLocked(scanResult);
+                    if (appIdCreated) {
+                        cleanUpAppIdCreation(scanResult);
+                    }
                     throw e;
                 }
             }
@@ -10837,27 +10844,32 @@
     }
 
 
-    /** Prepares the system to commit a {@link ScanResult} in a way that will not fail. */
-    private void prepareScanResultLocked(@NonNull ScanResult result)
+    /**
+     * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering
+     * the app ID required for reconcile.
+     * @return {@code true} if a new app ID was registered and will need to be cleaned up on
+     *         failure.
+     */
+    private boolean optimisticallyRegisterAppId(@NonNull ScanResult result)
             throws PackageManagerException {
         if (!result.existingSettingCopied) {
             // THROWS: when we can't allocate a user id. add call to check if there's
             // enough space to ensure we won't throw; otherwise, don't modify state
-            mSettings.registerAppIdLPw(result.pkgSetting);
+            return mSettings.registerAppIdLPw(result.pkgSetting);
         }
+        return false;
     }
 
     /**
-     * Reverts any changes to the system that were made by
-     * {@link #prepareScanResultLocked(ScanResult)}
+     * Reverts any app ID creation that were made by
+     * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the
+     * referenced method returned true.
      */
-    private void unprepareScanResultLocked(@NonNull ScanResult result) {
-        if (!result.existingSettingCopied) {
-            // iff we've acquired an app ID for a new package setting, remove it so that it can be
-            // acquired by another request.
-            if (result.pkgSetting.appId > 0) {
-                mSettings.removeAppIdLPw(result.pkgSetting.appId);
-            }
+    private void cleanUpAppIdCreation(@NonNull ScanResult result) {
+        // iff we've acquired an app ID for a new package setting, remove it so that it can be
+        // acquired by another request.
+        if (result.pkgSetting.appId > 0) {
+            mSettings.removeAppIdLPw(result.pkgSetting.appId);
         }
     }
 
@@ -16701,6 +16713,7 @@
         final Map<String, VersionInfo> versionInfos = new ArrayMap<>(requests.size());
         final Map<String, PackageSetting> lastStaticSharedLibSettings =
                 new ArrayMap<>(requests.size());
+        final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
         boolean success = false;
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
@@ -16740,7 +16753,7 @@
                                             + " in multi-package install request.");
                             return;
                         }
-                        prepareScanResultLocked(result);
+                        createdAppId.put(packageName, optimisticallyRegisterAppId(result));
                         versionInfos.put(result.pkgSetting.pkg.packageName,
                                 getSettingsVersionForPackage(result.pkgSetting.pkg));
                         if (result.staticSharedLibraryInfo != null) {
@@ -16797,7 +16810,9 @@
         } finally {
             if (!success) {
                 for (ScanResult result : preparedScans.values()) {
-                    unprepareScanResultLocked(result);
+                    if (createdAppId.getOrDefault(result.request.pkg.packageName, false)) {
+                        cleanUpAppIdCreation(result);
+                    }
                 }
             }
             for (PrepareResult result : prepareResults.values()) {
@@ -19890,26 +19905,28 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "replace preferred activity");
-        synchronized (mPackages) {
-            if (mContext.checkCallingOrSelfPermission(
-                    android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
-                    != PackageManager.PERMISSION_GRANTED) {
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
+                != PackageManager.PERMISSION_GRANTED) {
+            synchronized (mPackages) {
                 if (getUidTargetSdkVersionLockedLPr(callingUid)
                         < Build.VERSION_CODES.FROYO) {
                     Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
                             + Binder.getCallingUid());
                     return;
                 }
-                mContext.enforceCallingOrSelfPermission(
-                        android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+        }
 
-            PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
+        synchronized (mPackages) {
+            final PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
             if (pir != null) {
                 // Get all of the existing entries that exactly match this filter.
-                ArrayList<PreferredActivity> existing = pir.findFilters(filter);
+                final ArrayList<PreferredActivity> existing = pir.findFilters(filter);
                 if (existing != null && existing.size() == 1) {
-                    PreferredActivity cur = existing.get(0);
+                    final PreferredActivity cur = existing.get(0);
                     if (DEBUG_PREFERRED) {
                         Slog.i(TAG, "Checking replace of preferred:");
                         filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
@@ -19939,14 +19956,13 @@
                         return;
                     }
                 }
-
                 if (existing != null) {
                     if (DEBUG_PREFERRED) {
                         Slog.i(TAG, existing.size() + " existing preferred matches for:");
                         filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
                     }
-                    for (int i = 0; i < existing.size(); i++) {
-                        PreferredActivity pa = existing.get(i);
+                    for (int i = existing.size() - 1; i >= 0; --i) {
+                        final PreferredActivity pa = existing.get(i);
                         if (DEBUG_PREFERRED) {
                             Slog.i(TAG, "Removing existing preferred activity "
                                     + pa.mPref.mComponent + ":");
@@ -19956,9 +19972,9 @@
                     }
                 }
             }
-            addPreferredActivityInternal(filter, match, set, activity, true, userId,
-                    "Replacing preferred");
         }
+        addPreferredActivityInternal(filter, match, set, activity, true, userId,
+                "Replacing preferred");
     }
 
     @Override
@@ -20032,7 +20048,7 @@
                     PreferredActivity pa = removed.get(j);
                     pir.removeFilter(pa);
                 }
-                outUserChanged.setValueAt(thisUserId, true);
+                outUserChanged.put(thisUserId, true);
             }
         }
     }
@@ -20752,8 +20768,16 @@
     }
 
     @Override
-    public String getAttentionServicePackageName() {
-        return mContext.getString(R.string.config_defaultAttentionService);
+    public @Nullable String getAttentionServicePackageName() {
+        final String flattenedComponentName =
+                mContext.getString(R.string.config_defaultAttentionService);
+        if (flattenedComponentName != null) {
+            ComponentName componentName = ComponentName.unflattenFromString(flattenedComponentName);
+            if (componentName != null && componentName.getPackageName() != null) {
+                return componentName.getPackageName();
+            }
+        }
+        return null;
     }
 
     private @Nullable String getDocumenterPackageName() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 4e4a0e4..6b804df 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2423,6 +2423,16 @@
                     sessionParams.setStaged();
                     break;
                 case "--enable-rollback":
+                    if (params.installerPackageName == null) {
+                        // com.android.shell has the TEST_MANAGE_ROLLBACKS
+                        // permission needed to enable rollback for non-module
+                        // packages, which is likely what the user wants when
+                        // enabling rollback through the shell command. Set
+                        // the installer to com.android.shell if no installer
+                        // has been provided so that the user doesn't have to
+                        // remember to set it themselves.
+                        params.installerPackageName = "com.android.shell";
+                    }
                     sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
                     break;
                 default:
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 41a8a77..dae07bd 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -810,15 +810,20 @@
 
     /**
      * Registers a user ID with the system. Potentially allocates a new user ID.
+     * @return {@code true} if a new app ID was created in the process. {@code false} can be
+     *         returned in the case that a shared user ID already exists or the explicit app ID is
+     *         already registered.
      * @throws PackageManagerException If a user ID could not be allocated.
      */
-    void registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+    boolean registerAppIdLPw(PackageSetting p) throws PackageManagerException {
+        final boolean createdNew;
         if (p.appId == 0) {
             // Assign new user ID
             p.appId = acquireAndRegisterNewAppIdLPw(p);
+            createdNew = true;
         } else {
             // Add new setting to list of user IDs
-            registerExistingAppIdLPw(p.appId, p, p.name);
+            createdNew = registerExistingAppIdLPw(p.appId, p, p.name);
         }
         if (p.appId < 0) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -826,6 +831,7 @@
             throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
                     "Package " + p.name + " could not be assigned a valid UID");
         }
+        return createdNew;
     }
 
     /**
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index d9d21ba..5e829b2 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -16,9 +16,14 @@
 
 package com.android.server.power;
 
+import static android.provider.Settings.System.ADAPTIVE_SLEEP;
+
+import android.Manifest;
 import android.attention.AttentionManagerInternal;
 import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -83,6 +88,12 @@
     @VisibleForTesting
     protected AttentionManagerInternal mAttentionManager;
 
+    @VisibleForTesting
+    protected PackageManager mPackageManager;
+
+    @VisibleForTesting
+    protected ContentResolver mContentResolver;
+
     /**
      * Current wakefulness of the device. {@see PowerManagerInternal}
      */
@@ -137,6 +148,8 @@
 
     public void systemReady(Context context) {
         updateEnabledFromSettings(context);
+        mPackageManager = context.getPackageManager();
+        mContentResolver = context.getContentResolver();
         mAttentionManager = LocalServices.getService(AttentionManagerInternal.class);
         mMaximumExtensionMillis = context.getResources().getInteger(
                 com.android.internal.R.integer.config_attentionMaximumExtension);
@@ -162,6 +175,11 @@
             return nextScreenDimming;
         }
 
+        if (!serviceHasSufficientPermissions()) {
+            Settings.System.putInt(mContentResolver, ADAPTIVE_SLEEP, 0);
+            return nextScreenDimming;
+        }
+
         final long now = SystemClock.uptimeMillis();
         final long whenToCheck = nextScreenDimming - getAttentionTimeout();
         final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis;
@@ -263,6 +281,18 @@
         return mAttentionManager != null && mAttentionManager.isAttentionServiceSupported();
     }
 
+    /**
+     * Returns {@code true} if the attention service has sufficient permissions, disables the
+     * depending features otherwise.
+     */
+    @VisibleForTesting
+    boolean serviceHasSufficientPermissions() {
+        final String attentionPackage = mPackageManager.getAttentionServicePackageName();
+        return attentionPackage != null && mPackageManager.checkPermission(
+                Manifest.permission.CAMERA, attentionPackage)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
     public void dump(PrintWriter pw) {
         pw.print("AttentionDetector:");
         pw.print(" mMaximumExtensionMillis=" + mMaximumExtensionMillis);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b2ac1b8..654c477 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -147,6 +147,8 @@
 
         mLegacyRoleResolver = legacyRoleResolver;
 
+        RoleControllerManager.initializeRemoteServiceComponentName(context);
+
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
 
@@ -231,7 +233,7 @@
             // Run grants again
             Slog.i(LOG_TAG, "Granting default permissions...");
             CompletableFuture<Void> result = new CompletableFuture<>();
-            getOrCreateControllerService(userId).grantDefaultRoles(FgThread.getExecutor(),
+            getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
                     successful -> {
                         if (successful) {
                             userState.setPackagesHash(packagesHash);
@@ -318,7 +320,7 @@
     }
 
     @NonNull
-    private RoleControllerManager getOrCreateControllerService(@UserIdInt int userId) {
+    private RoleControllerManager getOrCreateController(@UserIdInt int userId) {
         synchronized (mLock) {
             RoleControllerManager controller = mControllers.get(userId);
             if (controller == null) {
@@ -330,7 +332,8 @@
                 } catch (NameNotFoundException e) {
                     throw new RuntimeException(e);
                 }
-                controller = new RoleControllerManager(context, FgThread.getHandler());
+                controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName(
+                        FgThread.getHandler(), context);
                 mControllers.put(userId, controller);
             }
             return controller;
@@ -474,7 +477,7 @@
             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
             Preconditions.checkNotNull(callback, "callback cannot be null");
 
-            getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, flags,
+            getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
                     callback);
         }
 
@@ -494,7 +497,7 @@
             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
             Preconditions.checkNotNull(callback, "callback cannot be null");
 
-            getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName, flags,
+            getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
                     callback);
         }
 
@@ -513,7 +516,7 @@
             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
             Preconditions.checkNotNull(callback, "callback cannot be null");
 
-            getOrCreateControllerService(userId).onClearRoleHolders(roleName, flags, callback);
+            getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
         }
 
         @Override
@@ -738,10 +741,10 @@
                 }
             });
             if (packageName != null) {
-                getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+                getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
                         packageName, 0, callback);
             } else {
-                getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+                getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
                         callback);
             }
             try {
@@ -762,10 +765,10 @@
                 }
             });
             if (packageName != null) {
-                getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
+                getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_BROWSER,
                         packageName, 0, callback);
             } else {
-                getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
+                getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_BROWSER, 0,
                         callback);
             }
         }
@@ -791,10 +794,10 @@
                 callback.accept(successful);
             });
             if (packageName != null) {
-                getOrCreateControllerService(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
+                getOrCreateController(userId).onAddRoleHolder(RoleManager.ROLE_HOME,
                         packageName, 0, remoteCallback);
             } else {
-                getOrCreateControllerService(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
+                getOrCreateController(userId).onClearRoleHolders(RoleManager.ROLE_HOME, 0,
                         remoteCallback);
             }
         }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 10ed88f..da9bc16 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -64,6 +64,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CoolingDevice;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -1798,6 +1799,28 @@
                 e.writeInt(temp.getType());
                 e.writeString(temp.getName());
                 e.writeInt((int) (temp.getValue() * 10));
+                e.writeInt(temp.getStatus());
+                pulledData.add(e);
+            }
+        } catch (RemoteException e) {
+            // Should not happen.
+            Slog.e(TAG, "Disconnected from thermal service. Cannot pull temperatures.");
+        } finally {
+            Binder.restoreCallingIdentity(callingToken);
+        }
+    }
+
+    private void pullCoolingDevices(int tagId, long elapsedNanos, long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        long callingToken = Binder.clearCallingIdentity();
+        try {
+            List<CoolingDevice> devices = sThermalService.getCurrentCoolingDevices();
+            for (CoolingDevice device : devices) {
+                StatsLogEventWrapper e =
+                        new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+                e.writeInt(device.getType());
+                e.writeString(device.getName());
+                e.writeInt((int) (device.getValue()));
                 pulledData.add(e);
             }
         } catch (RemoteException e) {
@@ -2084,6 +2107,9 @@
                 e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
                         Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, 0,
                         userId) != 0);
+                e.writeBoolean(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.FACE_UNLOCK_DIVERSITY_REQUIRED, 1,
+                        userId) != 0);
 
                 pulledData.add(e);
             }
@@ -2268,6 +2294,10 @@
                 pullTemperature(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.COOLING_DEVICE: {
+                pullCoolingDevices(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             case StatsLog.DEBUG_ELAPSED_CLOCK: {
                 pullDebugElapsedClock(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
@@ -2532,12 +2562,9 @@
     private static final class ThermalEventListener extends IThermalEventListener.Stub {
         @Override
         public void notifyThrottling(Temperature temp) {
-            boolean isThrottling = temp.getStatus() >= Temperature.THROTTLING_SEVERE;
             StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
-                    isThrottling ?
-                            StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__START :
-                            StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__STOP,
-                    temp.getValue());
+                    StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__UNKNOWN,
+                    temp.getValue(), temp.getStatus(), temp.getName());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index b287a0b..7eac07c 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -457,7 +457,7 @@
                     "pendingActivityLaunch");
             try {
                 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
-                        resume, pal.r.pendingOptions, null, null /* outRecords */);
+                        resume, pal.r.pendingOptions, null);
             } catch (Exception e) {
                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
                 pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 8957444..4ef8753 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -544,11 +544,17 @@
      */
     int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
-            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
-            ActivityRecord[] outActivity) {
+            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
         try {
-            return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
-                    doResume, options, inTask, outActivity);
+            mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(r.intent);
+            mLastStartReason = "startResolvedActivity";
+            mLastStartActivityTimeMs = System.currentTimeMillis();
+            mLastStartActivityRecord[0] = r;
+            mLastStartActivityResult = startActivity(r, sourceRecord, voiceSession, voiceInteractor,
+                    startFlags, doResume, options, inTask, mLastStartActivityRecord);
+            mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(mLastStartActivityResult,
+                    mLastStartActivityRecord[0]);
+            return mLastStartActivityResult;
         } finally {
             onExecutionComplete();
         }
@@ -965,8 +971,9 @@
                 : (realCallingUid == Process.SYSTEM_UID)
                         || realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
         if (realCallingUid != callingUid) {
-            // don't abort if the realCallingUid has a visible window
-            if (realCallingUidHasAnyVisibleWindow) {
+            // don't abort if the realCallingUid has a visible window, unless realCallingUid is
+            // SYSTEM_UID, in which case it start needs to be explicitly whitelisted
+            if (realCallingUidHasAnyVisibleWindow && realCallingUid != Process.SYSTEM_UID) {
                 return false;
             }
             // if the realCallingUid is a persistent system process, abort if the IntentSender
@@ -980,31 +987,6 @@
                 return false;
             }
         }
-        // If we don't have callerApp at this point, no caller was provided to startActivity().
-        // That's the case for PendingIntent-based starts, since the creator's process might not be
-        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
-        // caller, so that we can make the decision based on its foreground/whitelisted state.
-        if (callerApp == null) {
-            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
-        }
-        if (callerApp != null) {
-            // don't abort if the callerApp is instrumenting with background activity starts privs
-            if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
-                return false;
-            }
-            // don't abort if the caller is currently temporarily whitelisted
-            if (callerApp.areBackgroundActivityStartsAllowed()) {
-                return false;
-            }
-            // don't abort if the caller has an activity in any foreground task
-            if (callerApp.hasActivityInVisibleTask()) {
-                return false;
-            }
-            // don't abort if the caller is bound by a UID that's currently foreground
-            if (isBoundByForegroundUid(callerApp)) {
-                return false;
-            }
-        }
         // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
         if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                 == PERMISSION_GRANTED) {
@@ -1029,6 +1011,33 @@
                     + " temporarily whitelisted. This will not be supported in future Q builds.");
             return false;
         }
+        // If we don't have callerApp at this point, no caller was provided to startActivity().
+        // That's the case for PendingIntent-based starts, since the creator's process might not be
+        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
+        // caller, so that we can make the decision based on its foreground/whitelisted state.
+        int callerAppUid = callingUid;
+        if (callerApp == null) {
+            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
+            callerAppUid = realCallingUid;
+        }
+        // don't abort if the callerApp or other processes of that uid are whitelisted in any way
+        if (callerApp != null) {
+            // first check the original calling process
+            if (callerApp.areBackgroundActivityStartsAllowed()) {
+                return false;
+            }
+            // only if that one wasn't whitelisted, check the other ones
+            final ArraySet<WindowProcessController> uidProcesses =
+                    mService.mProcessMap.getProcesses(callerAppUid);
+            if (uidProcesses != null) {
+                for (int i = uidProcesses.size() - 1; i >= 0; i--) {
+                    final WindowProcessController proc = uidProcesses.valueAt(i);
+                    if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
+                        return false;
+                    }
+                }
+            }
+        }
         // anything that has fallen through would currently be aborted
         Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                 + "; callingUid: " + callingUid
@@ -1053,17 +1062,6 @@
         return true;
     }
 
-    private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
-        final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
-        for (int i = boundClientUids.size() - 1; i >= 0; --i) {
-            final int uid = boundClientUids.valueAt(i);
-            if (mService.isUidForeground(uid)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     // TODO: remove this toast after feature development is done
     void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
         final Resources res = mService.mContext.getResources();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 76774d7..3fa0268 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -373,8 +373,8 @@
     private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
     /** All processes currently running that might have a window organized by name. */
     final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
-    /** All processes we currently have running mapped by pid */
-    final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+    /** All processes we currently have running mapped by pid and uid */
+    final WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
     /** This is the process holding what we currently consider to be the "home" activity. */
     WindowProcessController mHomeProcess;
     /** The currently running heavy-weight process, if any. */
@@ -913,7 +913,7 @@
             return getGlobalConfiguration();
         }
         synchronized (mGlobalLock) {
-            final WindowProcessController app = mPidMap.get(pid);
+            final WindowProcessController app = mProcessMap.getProcess(pid);
             return app != null ? app.getConfiguration() : getGlobalConfiguration();
         }
     }
@@ -4640,7 +4640,7 @@
         enforceSystemHasVrFeature();
         synchronized (mGlobalLock) {
             final int pid = Binder.getCallingPid();
-            final WindowProcessController wpc = mPidMap.get(pid);
+            final WindowProcessController wpc = mProcessMap.getProcess(pid);
             mVrController.setVrThreadLocked(tid, pid, wpc);
         }
     }
@@ -4659,7 +4659,7 @@
         enforceSystemHasVrFeature();
         synchronized (mGlobalLock) {
             final int pid = Binder.getCallingPid();
-            final WindowProcessController proc = mPidMap.get(pid);
+            final WindowProcessController proc = mProcessMap.getProcess(pid);
             mVrController.setPersistentVrThreadLocked(tid, pid, proc);
         }
     }
@@ -5204,9 +5204,10 @@
             mH.sendMessage(msg);
         }
 
-        for (int i = mPidMap.size() - 1; i >= 0; i--) {
-            final int pid = mPidMap.keyAt(i);
-            final WindowProcessController app = mPidMap.get(pid);
+        SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
+        for (int i = pidMap.size() - 1; i >= 0; i--) {
+            final int pid = pidMap.keyAt(i);
+            final WindowProcessController app = pidMap.get(pid);
             if (DEBUG_CONFIGURATION) {
                 Slog.v(TAG_CONFIGURATION, "Update process config of "
                         + app.mName + " to new config " + configCopy);
@@ -5859,7 +5860,7 @@
     }
 
     WindowProcessController getProcessController(int pid, int uid) {
-        final WindowProcessController proc = mPidMap.get(pid);
+        final WindowProcessController proc = mProcessMap.getProcess(pid);
         if (proc == null) return null;
         if (UserHandle.isApp(uid) && proc.mUid == uid) {
             return proc;
@@ -6423,14 +6424,14 @@
         @Override
         public void onProcessMapped(int pid, WindowProcessController proc) {
             synchronized (mGlobalLock) {
-                mPidMap.put(pid, proc);
+                mProcessMap.put(pid, proc);
             }
         }
 
         @Override
         public void onProcessUnMapped(int pid) {
             synchronized (mGlobalLock) {
-                mPidMap.remove(pid);
+                mProcessMap.remove(pid);
             }
         }
 
@@ -6503,7 +6504,7 @@
                     }
                     return;
                 }
-                final WindowProcessController process = mPidMap.get(pid);
+                final WindowProcessController process = mProcessMap.getProcess(pid);
                 if (process == null) {
                     if (DEBUG_CONFIGURATION) {
                         Slog.w(TAG, "Trying to update display configuration for invalid "
@@ -6696,7 +6697,7 @@
                     // Only allow this from foreground processes, so that background
                     // applications can't abuse it to prevent system UI from being shown.
                     if (uid >= FIRST_APPLICATION_UID) {
-                        final WindowProcessController proc = mPidMap.get(pid);
+                        final WindowProcessController proc = mProcessMap.getProcess(pid);
                         if (!proc.isPerceptible()) {
                             Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
                                     + " from background process " + proc);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index c1d872f..b5e7067 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -435,6 +435,18 @@
                 moveFromFullscreen, moveToFullscreen, animationType);
     }
 
+    /**
+     * Cancel existing animation if the destination was modified.
+     */
+    void cancel(final BoundsAnimationTarget target) {
+        final BoundsAnimator existing = mRunningAnimations.get(target);
+        if (existing != null) {
+            // Cancel animation. Since its already started, send animation end to client.
+            if (DEBUG) Slog.d(TAG, "cancel: mTarget= " + target);
+            existing.cancelAndCallAnimationEnd();
+        }
+    }
+
     @VisibleForTesting
     BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
             int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index c8f8e82..104805f 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -48,6 +48,7 @@
 import android.os.RemoteException;
 import android.util.AtomicFile;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml;
 
 public final class CompatModePackages {
@@ -324,8 +325,9 @@
             ActivityRecord starting = stack.restartPackage(packageName);
 
             // Tell all processes that loaded this package about the change.
-            for (int i = mService.mPidMap.size() - 1; i >= 0; i--) {
-                final WindowProcessController app = mService.mPidMap.valueAt(i);
+            SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap();
+            for (int i = pidMap.size() - 1; i >= 0; i--) {
+                final WindowProcessController app = pidMap.valueAt(i);
                 if (!app.mPkgList.contains(packageName)) {
                     continue;
                 }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 1934e25..bd874ba 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -28,6 +28,7 @@
 import static android.view.InsetsState.TYPE_TOP_BAR;
 import static android.view.InsetsState.TYPE_TOP_GESTURES;
 import static android.view.InsetsState.TYPE_TOP_TAPPABLE_ELEMENT;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
@@ -1230,7 +1231,7 @@
         final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0;
 
         if (layoutInScreenAndInsetDecor && !screenDecor) {
-            if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+            if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
                 outFrame.set(displayFrames.mUnrestricted);
             } else {
                 outFrame.set(displayFrames.mRestricted);
@@ -1290,7 +1291,7 @@
                 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
         if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
                 || forceWindowDrawsBarBackgrounds) {
-            impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+            impliedFlags |= SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
             impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
         }
         return impliedFlags;
@@ -1722,6 +1723,22 @@
             of.set(displayFrames.mDock);
             df.set(displayFrames.mDock);
         } else {
+
+            // In case we forced the window to draw behind the navigation bar, restrict df/of to
+            // DF.RestrictedOverscan to simulate old compat behavior.
+            Rect parentDisplayFrame = attached.getDisplayFrameLw();
+            Rect parentOverscan = attached.getOverscanFrameLw();
+            final WindowManager.LayoutParams attachedAttrs = attached.mAttrs;
+            if ((attachedAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
+                    && (attachedAttrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+                    && (attachedAttrs.systemUiVisibility
+                            & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0) {
+                parentOverscan = new Rect(parentOverscan);
+                parentOverscan.intersect(displayFrames.mRestrictedOverscan);
+                parentDisplayFrame = new Rect(parentDisplayFrame);
+                parentDisplayFrame.intersect(displayFrames.mRestrictedOverscan);
+            }
+
             // The effective display frame of the attached window depends on whether it is taking
             // care of insetting its content. If not, we need to use the parent's content frame so
             // that the entire window is positioned within that content. Otherwise we can use the
@@ -1733,7 +1750,7 @@
                 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
                 // Otherwise, use the overscan frame.
                 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
-                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
+                        ? attached.getContentFrameLw() : parentOverscan);
             } else {
                 // If the window is resizing, then we want to base the content frame on our attached
                 // content frame to resize...however, things can be tricky if the attached window is
@@ -1747,8 +1764,8 @@
                     cf.intersectUnchecked(displayFrames.mContent);
                 }
             }
-            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
-            of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
+            df.set(insetDecors ? parentDisplayFrame : cf);
+            of.set(insetDecors ? parentOverscan : cf);
             vf.set(attached.getVisibleFrameLw());
         }
         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be
@@ -1956,7 +1973,7 @@
                         of.set(displayFrames.mOverscan);
                         df.set(displayFrames.mOverscan);
                         pf.set(displayFrames.mOverscan);
-                    } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+                    } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
                             && (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW
                             || type == TYPE_VOLUME_OVERLAY)) {
                         // Asking for layout as if the nav bar is hidden, lets the application
@@ -2006,7 +2023,7 @@
                 }
             } else if (layoutInScreen || (sysUiFl
                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
+                    | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle()
                         + "): IN_SCREEN");
                 // A window that has requested to fill the entire screen just
@@ -2051,7 +2068,7 @@
                     of.set(displayFrames.mOverscan);
                     df.set(displayFrames.mOverscan);
                     pf.set(displayFrames.mOverscan);
-                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+                } else if ((sysUiFl & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
                         && (type == TYPE_STATUS_BAR
                         || type == TYPE_TOAST
                         || type == TYPE_DOCK_DIVIDER
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index 3d20501..d774dc3 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -90,8 +90,6 @@
         mShowDelayMs = getNavBarExitDuration() * 3;
         mPanicThresholdMs = context.getResources()
                 .getInteger(R.integer.config_immersive_mode_confirmation_panic);
-        mWindowManager = (WindowManager)
-                mContext.getSystemService(Context.WINDOW_SERVICE);
         mVrModeEnabled = vrModeEnabled;
     }
 
@@ -177,7 +175,7 @@
     private void handleHide() {
         if (mClingWindow != null) {
             if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation");
-            mWindowManager.removeView(mClingWindow);
+            getWindowManager().removeView(mClingWindow);
             mClingWindow = null;
         }
     }
@@ -275,7 +273,7 @@
             super.onAttachedToWindow();
 
             DisplayMetrics metrics = new DisplayMetrics();
-            mWindowManager.getDefaultDisplay().getMetrics(metrics);
+            getWindowManager().getDefaultDisplay().getMetrics(metrics);
             float density = metrics.density;
 
             getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
@@ -341,6 +339,19 @@
         }
     }
 
+    /**
+     * DO HOLD THE WINDOW MANAGER LOCK WHEN CALLING THIS METHOD
+     * The reason why we add this method is to avoid the deadlock of WMG->WMS and WMS->WMG
+     * when ImmersiveModeConfirmation object is created.
+     */
+    private WindowManager getWindowManager() {
+        if (mWindowManager == null) {
+            mWindowManager = (WindowManager)
+                      mContext.getSystemService(Context.WINDOW_SERVICE);
+        }
+        return mWindowManager;
+    }
+
     private void handleShow() {
         if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation");
 
@@ -352,7 +363,7 @@
 
         // show the confirmation
         WindowManager.LayoutParams lp = getClingWindowLayoutParams();
-        mWindowManager.addView(mClingWindow, lp);
+        getWindowManager().addView(mClingWindow, lp);
     }
 
     private final Runnable mConfirm = new Runnable() {
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index d6c7b21..7dcbedf 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -60,7 +60,6 @@
 import android.os.Environment;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -185,7 +184,6 @@
     // front. Newly created tasks, or tasks that are removed from the list will continue to change
     // the list.  This does not affect affiliated tasks.
     private boolean mFreezeTaskListReordering;
-    private long mFreezeTaskListReorderingTime;
     private long mFreezeTaskListTimeoutMs = FREEZE_TASK_LIST_TIMEOUT_MS;
 
     // Mainly to avoid object recreation on multiple calls.
@@ -220,6 +218,9 @@
         }
     };
 
+    private final Runnable mResetFreezeTaskListOnTimeoutRunnable =
+            this::resetFreezeTaskListReorderingOnTimeout;
+
     @VisibleForTesting
     RecentTasks(ActivityTaskManagerService service, TaskPersister taskPersister) {
         mService = service;
@@ -255,8 +256,7 @@
     }
 
     @VisibleForTesting
-    void setFreezeTaskListTimeoutParams(long reorderingTime, long timeoutMs) {
-        mFreezeTaskListReorderingTime = reorderingTime;
+    void setFreezeTaskListTimeout(long timeoutMs) {
         mFreezeTaskListTimeoutMs = timeoutMs;
     }
 
@@ -272,7 +272,8 @@
         // Always update the reordering time when this is called to ensure that the timeout
         // is reset
         mFreezeTaskListReordering = true;
-        mFreezeTaskListReorderingTime = SystemClock.elapsedRealtime();
+        mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
+        mService.mH.postDelayed(mResetFreezeTaskListOnTimeoutRunnable, mFreezeTaskListTimeoutMs);
     }
 
     /**
@@ -286,6 +287,7 @@
 
         // Once we end freezing the task list, reset the existing task order to the stable state
         mFreezeTaskListReordering = false;
+        mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
 
         // If the top task is provided, then restore the top task to the front of the list
         if (topTask != null) {
@@ -295,6 +297,8 @@
 
         // Resume trimming tasks
         trimInactiveRecentTasks();
+
+        mService.getTaskChangeNotificationController().notifyTaskStackChanged();
     }
 
     /**
@@ -302,13 +306,8 @@
      * before we need to iterate the task list in order (either for purposes of returning the list
      * to SystemUI or if we need to trim tasks in order)
      */
+    @VisibleForTesting
     void resetFreezeTaskListReorderingOnTimeout() {
-        // Unfreeze the recent task list if the time heuristic has passed
-        if (mFreezeTaskListReorderingTime
-                > (SystemClock.elapsedRealtime() - mFreezeTaskListTimeoutMs)) {
-            return;
-        }
-
         final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
         final TaskRecord topTask = focusedStack != null
                 ? focusedStack.topTask()
@@ -875,9 +874,6 @@
         final Set<Integer> includedUsers = getProfileIds(userId);
         includedUsers.add(Integer.valueOf(userId));
 
-        // Check if the frozen task list has timed out
-        resetFreezeTaskListReorderingOnTimeout();
-
         final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
         final int size = mTasks.size();
         int numVisibleTasks = 0;
@@ -1654,8 +1650,8 @@
         pw.println("mRecentsUid=" + mRecentsUid);
         pw.println("mRecentsComponent=" + mRecentsComponent);
         pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
-        pw.println("mFreezeTaskListReorderingTime (time since)="
-                + (SystemClock.elapsedRealtime() - mFreezeTaskListReorderingTime) + "ms");
+        pw.println("mFreezeTaskListReorderingPendingTimeout="
+                + mService.mH.hasCallbacks(mResetFreezeTaskListOnTimeoutRunnable));
         if (mTasks.isEmpty()) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f9fd541..9f42324 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -312,11 +313,12 @@
 
     /**
      * Returns true if the callingUid has any non-toast window currently visible to the user.
+     * Also ignores TYPE_APPLICATION_STARTING, since those windows don't belong to apps.
      */
     boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
         return forAllWindows(w ->
                         w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
-                        && w.isVisibleNow(),
+                        && w.mAttrs.type != TYPE_APPLICATION_STARTING && w.isVisibleNow(),
                 true /* traverseTopToBottom */);
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index bdb4d04..7515b3f 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -388,7 +388,9 @@
      * @return true if bounds were updated to some non-empty value.
      */
     boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
+        boolean animating = false;
         if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+            animating = true;
             getFinalAnimationBounds(mTmpRect2);
         } else {
             mTmpRect2.set(inOutBounds);
@@ -398,6 +400,13 @@
         if (updated) {
             inOutBounds.set(mTmpRect3);
 
+            // The final boundary is updated while there is an existing boundary animation. Let's
+            // cancel this animation to prevent the obsolete animation overwritten updated bounds.
+            if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
+                final DisplayContent displayContent = getDisplayContent();
+                displayContent.mBoundsAnimationController.getHandler().post(() ->
+                        displayContent.mBoundsAnimationController.cancel(this));
+            }
             // Once we've set the bounds based on the rotation of the old bounds in the new
             // orientation, clear the animation target bounds since they are obsolete, and
             // cancel any currently running animations
@@ -1585,7 +1594,6 @@
 
             mBoundsAnimatingRequested = false;
             mBoundsAnimating = true;
-            mCancelCurrentBoundsAnimation = false;
             mAnimationType = animationType;
 
             // If we are changing UI mode, as in the PiP to fullscreen
@@ -1645,7 +1653,7 @@
                         mBoundsAnimationTarget, false /* forceUpdate */);
             }
 
-            if (finalStackSize != null) {
+            if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
                 setPinnedStackSize(finalStackSize, null);
             } else {
                 // We have been canceled, so the final stack size is null, still run the
@@ -1758,6 +1766,7 @@
         }
 
         final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
+        mCancelCurrentBoundsAnimation = false;
         displayContent.mBoundsAnimationController.getHandler().post(() -> {
             displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
                     finalToBounds, animationDuration, finalSchedulePipModeChangedState,
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 4ca35f7..eb919eb 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -372,18 +372,39 @@
         mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
     }
 
-    public boolean areBackgroundActivityStartsAllowed() {
-        return mAllowBackgroundActivityStarts;
+    boolean areBackgroundActivityStartsAllowed() {
+        // allow if the whitelisting flag was explicitly set
+        if (mAllowBackgroundActivityStarts) {
+            return true;
+        }
+        // allow if the proc is instrumenting with background activity starts privs
+        if (mInstrumentingWithBackgroundActivityStartPrivileges) {
+            return true;
+        }
+        // allow if the caller has an activity in any foreground task
+        if (hasActivityInVisibleTask()) {
+            return true;
+        }
+        // allow if the caller is bound by a UID that's currently foreground
+        if (isBoundByForegroundUid()) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isBoundByForegroundUid() {
+        for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
+            if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
+                return true;
+            }
+        }
+        return false;
     }
 
     public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
         mBoundClientUids = boundClientUids;
     }
 
-    public ArraySet<Integer> getBoundClientUids() {
-        return mBoundClientUids;
-    }
-
     public void setInstrumenting(boolean instrumenting,
             boolean hasBackgroundActivityStartPrivileges) {
         mInstrumenting = instrumenting;
@@ -394,14 +415,6 @@
         return mInstrumenting;
     }
 
-    /**
-     * @return true if the instrumentation was started by a holder of
-     * START_ACTIVITIES_FROM_BACKGROUND permission
-     */
-    boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
-        return mInstrumentingWithBackgroundActivityStartPrivileges;
-    }
-
     public void setPerceptible(boolean perceptible) {
         mPerceptible = perceptible;
     }
@@ -487,7 +500,7 @@
         }
     }
 
-    boolean hasActivityInVisibleTask() {
+    private boolean hasActivityInVisibleTask() {
         for (int i = mActivities.size() - 1; i >= 0; --i) {
             TaskRecord task = mActivities.get(i).getTaskRecord();
             if (task == null) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessControllerMap.java b/services/core/java/com/android/server/wm/WindowProcessControllerMap.java
new file mode 100644
index 0000000..2767972
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowProcessControllerMap.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.server.wm;
+
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import java.util.Map;
+import java.util.HashMap;
+
+final class WindowProcessControllerMap {
+
+    /** All processes we currently have running mapped by pid */
+    private final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
+    /** All processes we currently have running mapped by uid */
+    private final Map<Integer, ArraySet<WindowProcessController>> mUidMap = new HashMap<>();
+
+    /** Retrieves a currently running process for pid. */
+    WindowProcessController getProcess(int pid) {
+        return mPidMap.get(pid);
+    }
+
+    /** Retrieves all currently running processes for uid. */
+    ArraySet<WindowProcessController> getProcesses(int uid) {
+        return mUidMap.get(uid);
+    }
+
+    SparseArray<WindowProcessController> getPidMap() {
+        return mPidMap;
+    }
+
+    void put(int pid, WindowProcessController proc) {
+        // if there is a process for this pid already in mPidMap it'll get replaced automagically,
+        // but we actually need to remove it from mUidMap too before adding the new one
+        final WindowProcessController prevProc = mPidMap.get(pid);
+        if (prevProc != null) {
+            removeProcessFromUidMap(prevProc);
+        }
+        // put process into mPidMap
+        mPidMap.put(pid, proc);
+        // put process into mUidMap
+        final int uid = proc.mUid;
+        ArraySet<WindowProcessController> procSet = mUidMap.getOrDefault(uid,
+                new ArraySet<WindowProcessController>());
+        procSet.add(proc);
+        mUidMap.put(uid, procSet);
+    }
+
+    void remove(int pid) {
+        final WindowProcessController proc = mPidMap.get(pid);
+        if (proc != null) {
+            // remove process from mPidMap
+            mPidMap.remove(pid);
+            // remove process from mUidMap
+            removeProcessFromUidMap(proc);
+        }
+    }
+
+    private void removeProcessFromUidMap(WindowProcessController proc) {
+        if (proc == null) {
+            return;
+        }
+        final int uid = proc.mUid;
+        ArraySet<WindowProcessController> procSet = mUidMap.get(uid);
+        if (procSet != null) {
+            procSet.remove(proc);
+            if (procSet.isEmpty()) {
+                mUidMap.remove(uid);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d990e6c..8e18683 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1305,7 +1305,7 @@
     void onDisplayChanged(DisplayContent dc) {
         super.onDisplayChanged(dc);
         // Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
-        if (dc != null) {
+        if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) {
             mLayoutSeq = dc.mLayoutSeq - 1;
             mInputWindowHandle.displayId = dc.getDisplayId();
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0cd730b..2a2de77 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -32,7 +32,6 @@
 import android.content.Intent;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
 import android.database.sqlite.SQLiteCompatibilityWalFlags;
@@ -1248,11 +1247,6 @@
             mSystemServiceManager.startService(CONTENT_SUGGESTIONS_SERVICE_CLASS);
             traceEnd();
 
-            // NOTE: ClipboardService indirectly depends on IntelligenceService
-            traceBeginAndSlog("StartClipboardService");
-            mSystemServiceManager.startService(ClipboardService.class);
-            traceEnd();
-
             traceBeginAndSlog("InitNetworkStackClient");
             try {
                 NetworkStackClient.getInstance().init();
@@ -1887,6 +1881,11 @@
             traceEnd();
         }
 
+        // NOTE: ClipboardService depends on ContentCapture and Autofill
+        traceBeginAndSlog("StartClipboardService");
+        mSystemServiceManager.startService(ClipboardService.class);
+        traceEnd();
+
         traceBeginAndSlog("AppServiceManager");
         mSystemServiceManager.startService(AppBindingService.Lifecycle.class);
         traceEnd();
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 339607b..59aea21 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.TrafficStatsConstants;
 
 import libcore.io.IoBridge;
 
@@ -586,7 +587,8 @@
     private boolean createSocket() {
         final int SEND_TIMEOUT_MS = 300;
 
-        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR);
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                TrafficStatsConstants.TAG_SYSTEM_NEIGHBOR);
         try {
             mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
             // Setting SNDTIMEO is purely for defensive purposes.
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 164570a..cc64323 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -86,6 +86,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.net.Uri;
 import android.os.ConditionVariable;
 import android.os.DeadObjectException;
@@ -100,6 +101,7 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
+import com.android.server.LocalServices;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.DataChangedJournal;
 import com.android.server.backup.KeyValueBackupJob;
@@ -116,7 +118,6 @@
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowApplicationPackageManager;
-import com.android.server.testing.shadows.ShadowBackupActivityThread;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -163,8 +164,7 @@
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEventLog.class,
-            ShadowQueuedWork.class,
-            ShadowBackupActivityThread.class,
+            ShadowQueuedWork.class
         })
 @Presubmit
 public class KeyValueBackupTaskTest {
@@ -179,6 +179,7 @@
     @Mock private IBackupObserver mObserver;
     @Mock private IBackupManagerMonitor mMonitor;
     @Mock private OnTaskFinishedListener mListener;
+    @Mock private PackageManagerInternal mPackageManagerInternal;
     private UserBackupManagerService mBackupManagerService;
     private TransportData mTransport;
     private ShadowLooper mShadowBackupLooper;
@@ -243,6 +244,11 @@
         mShadowBackupLooper = shadowOf(mBackupHandler.getLooper());
         ShadowEventLog.setUp();
         mReporter = spy(new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor));
+
+        when(mPackageManagerInternal.getApplicationEnabledState(any(), anyInt()))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
     }
 
     @After
@@ -471,7 +477,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
 
         runTask(task);
@@ -484,7 +490,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task =
                 createKeyValueBackupTask(transportMock, true, PACKAGE_1, PM_PACKAGE);
 
@@ -498,7 +504,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgentWithData(PACKAGE_1);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, false, PACKAGE_1);
 
         runTask(task);
@@ -1307,7 +1313,7 @@
                         argThat(packageInfo(PM_PACKAGE)), any(), anyInt()))
                 .then(copyBackupDataTo(backupDataPath));
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         agentOnBackupDo(
                 pmAgent,
                 (oldState, dataOutput, newState) -> {
@@ -1371,7 +1377,7 @@
         setUpAgent(PACKAGE_1);
         when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         agentOnBackupDo(
                 pmAgent,
                 (oldState, dataOutput, newState) -> {
@@ -1395,7 +1401,7 @@
         setUpAgent(PACKAGE_1);
         when(transportMock.transport.finishBackup()).thenReturn(BackupTransport.TRANSPORT_OK);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         agentOnBackupDo(
                 pmAgent,
                 (oldState, dataOutput, newState) -> {
@@ -1957,7 +1963,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
         BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
@@ -1970,7 +1976,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
         BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
@@ -1983,7 +1989,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
         BackupAgent pmAgent = createThrowingPmAgent(new RuntimeException());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(pmAgent);
+        doReturn(pmAgent).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
 
         runTask(task);
@@ -1996,7 +2002,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         agentOnBackupDo(
                 pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
@@ -2011,7 +2017,7 @@
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
         BackupAgent pmAgent = spy(createPmAgent());
-        when(mBackupManagerService.makeMetadataAgent()).thenReturn(forward(pmAgent));
+        doReturn(forward(pmAgent)).when(mBackupManagerService).makeMetadataAgent();
         KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
         agentOnBackupDo(
                 pmAgent, (oldState, dataOutput, newState) -> runInWorkerThread(task::markCancel));
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java
deleted file mode 100644
index ca2e3b6..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupActivityThread.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.testing.shadows;
-
-import android.app.ActivityThread;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowActivityThread;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import javax.annotation.Nonnull;
-
-/**
- * Extends the existing {@link ShadowActivityThread} to add support for
- * {@link PackageManager#getApplicationEnabledSetting(String)} in the shadow {@link PackageManager}
- * returned  by {@link ShadowBackupActivityThread#getPackageManager()}.
- */
-@Implements(value = ActivityThread.class, isInAndroidSdk = false, looseSignatures = true)
-public class ShadowBackupActivityThread extends ShadowActivityThread {
-    @Implementation
-    public static Object getPackageManager() {
-        ClassLoader classLoader = ShadowActivityThread.class.getClassLoader();
-        Class<?> iPackageManagerClass;
-        try {
-            iPackageManagerClass = classLoader.loadClass("android.content.pm.IPackageManager");
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException(e);
-        }
-
-        return Proxy.newProxyInstance(
-                classLoader,
-                new Class[] {iPackageManagerClass},
-                new InvocationHandler() {
-                    @Override
-                    public Object invoke(Object proxy, @Nonnull Method method, Object[] args)
-                            throws Exception {
-                        if (method.getName().equals("getApplicationInfo")) {
-                            String packageName = (String) args[0];
-                            int flags = (Integer) args[1];
-
-                            try {
-                                return RuntimeEnvironment.application
-                                        .getPackageManager()
-                                        .getApplicationInfo(packageName, flags);
-                            } catch (PackageManager.NameNotFoundException e) {
-                                throw new RemoteException(e.getMessage());
-                            }
-                        } else if (method.getName().equals("getApplicationEnabledSetting")) {
-                            return 0;
-                        } else {
-                            return null;
-                        }
-                    }
-                });
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 2cba9d0..2977414 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -17,6 +17,7 @@
 package com.android.server.accessibility;
 
 import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
 
@@ -116,6 +117,7 @@
 
     MotionEvent mClickDownEvent;
     MotionEvent mClickUpEvent;
+    MotionEvent mHoverMoveEvent;
 
     ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
     ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
@@ -152,6 +154,10 @@
                 CLICK_POINT.y, 0);
         mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
 
+        mHoverMoveEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, CLICK_POINT.x, CLICK_POINT.y,
+                0);
+        mHoverMoveEvent.setSource(InputDevice.SOURCE_MOUSE);
+
         mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
                 hasTimeFromDown(0));
         mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
@@ -301,6 +307,23 @@
     }
 
     @Test
+    public void
+            testOnMotionEvents_fromMouseWithInjectedGestureInProgress_shouldNotCancelAndPassReal()
+            throws RemoteException {
+        EventStreamTransformation next = attachMockNext(mMotionEventInjector);
+        injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
+        mMessageCapturingHandler.sendOneMessage(); // Send a motion event
+        mMotionEventInjector.onMotionEvent(mHoverMoveEvent, mHoverMoveEvent, 0);
+        mMessageCapturingHandler.sendAllMessages();
+
+        verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
+        assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
+        assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
+        assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
+        verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
+    }
+
+    @Test
     public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
             throws RemoteException {
         EventStreamTransformation next = attachMockNext(mMotionEventInjector);
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
new file mode 100644
index 0000000..8426a0b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.attention;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.service.attention.IAttentionCallback;
+import android.service.attention.IAttentionService;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionHandler;
+import com.android.server.attention.AttentionManagerService.UserState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.attention.AttentionManagerService}
+ */
+@SmallTest
+public class AttentionManagerServiceTest {
+    private AttentionManagerService mSpyAttentionManager;
+    private UserState mSpyUserState;
+    private final int mTimeout = 1000;
+    @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
+    @Mock private AttentionHandler mMockHandler;
+    @Mock private IAttentionCallback mMockIAttentionCallback;
+    @Mock private IPowerManager mMockIPowerManager;
+    @Mock Context mContext;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        // setup context mock
+        doReturn(true).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any());
+        // setup power manager mock
+        PowerManager mPowerManager;
+        doReturn(true).when(mMockIPowerManager).isInteractive();
+        mPowerManager = new PowerManager(mContext, mMockIPowerManager, null);
+
+        Object mLock = new Object();
+        // setup a spy on attention manager
+        AttentionManagerService mAttentionManager = new AttentionManagerService(
+                mContext,
+                mPowerManager,
+                mLock,
+                mMockHandler);
+        mSpyAttentionManager = Mockito.spy(mAttentionManager);
+        // setup a spy on user state
+        ComponentName componentName = new ComponentName("a", "b");
+        mSpyAttentionManager.mComponentName = componentName;
+        UserState mUserState = new UserState(0,
+                mContext,
+                mLock,
+                componentName);
+        mUserState.mService = new MockIAttentionService();
+        mSpyUserState = spy(mUserState);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_noCrashWhenNoUserStateLocked() {
+        mSpyAttentionManager.cancelAttentionCheck(null);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_noCrashWhenCallbackMismatched() {
+        mSpyUserState.mCurrentAttentionCheck =
+                new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+        doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+        mSpyAttentionManager.cancelAttentionCheck(null);
+    }
+
+    @Test
+    public void testCancelAttentionCheck_cancelCallbackWhenMatched() {
+        mSpyUserState.mCurrentAttentionCheck =
+                new AttentionCheck(mMockAttentionCallbackInternal, mMockIAttentionCallback);
+        doReturn(mSpyUserState).when(mSpyAttentionManager).peekCurrentUserStateLocked();
+        mSpyAttentionManager.cancelAttentionCheck(mMockAttentionCallbackInternal);
+        verify(mSpyAttentionManager).cancel(any());
+    }
+
+    @Test
+    public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
+        doReturn(false).when(mMockIPowerManager).isInteractive();
+        AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+        assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
+    }
+
+    @Test
+    public void testCheckAttention_callOnSuccess() throws RemoteException {
+        doReturn(true).when(mSpyAttentionManager).isServiceEnabled();
+        doReturn(true).when(mMockIPowerManager).isInteractive();
+        doReturn(mSpyUserState).when(mSpyAttentionManager).getOrCreateCurrentUserStateLocked();
+        doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
+
+        AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
+        mSpyAttentionManager.checkAttention(mTimeout, callback);
+        verify(callback).onSuccess(anyInt(), anyLong());
+    }
+
+    private class MockIAttentionService implements IAttentionService {
+        public void checkAttention(IAttentionCallback callback) throws RemoteException {
+            callback.onSuccess(0, 0);
+        }
+        public void cancelAttentionCheck(IAttentionCallback callback) {
+        }
+        public IBinder asBinder() {
+            return null;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
deleted file mode 100644
index 97a6e66..0000000
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*
- * 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.backup.testutils;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ChangedPackages;
-import android.content.pm.IDexModuleRegisterCallback;
-import android.content.pm.IOnPermissionsChangeListener;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageDeleteObserver2;
-import android.content.pm.IPackageInstaller;
-import android.content.pm.IPackageManager;
-import android.content.pm.IPackageMoveObserver;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.KeySet;
-import android.content.pm.ModuleInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.pm.SuspendDialogInfo;
-import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.VersionedPackage;
-import android.content.pm.dex.IArtManager;
-import android.graphics.Bitmap;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-import android.os.RemoteException;
-
-import java.util.List;
-
-/**
- * Stub for IPackageManager to use in tests.
- */
-public class IPackageManagerStub implements IPackageManager {
-    public static PackageInfo sPackageInfo;
-    public static int sApplicationEnabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-
-    @Override
-    public PackageInfo getPackageInfo(String packageName, int flags, int userId)
-        throws RemoteException {
-        return sPackageInfo;
-    }
-
-    @Override
-    public int getApplicationEnabledSetting(String packageName, int userId) throws RemoteException {
-        return sApplicationEnabledSetting;
-    }
-
-    @Override
-    public void checkPackageStartable(String packageName, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public boolean isPackageAvailable(String packageName, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage, int flags,
-        int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public int getPackageUid(String packageName, int flags, int userId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int[] getPackageGids(String packageName, int flags, int userId) throws RemoteException {
-        return new int[0];
-    }
-
-    @Override
-    public String[] currentToCanonicalPackageNames(String[] names) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public String[] canonicalToCurrentPackageNames(String[] names) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public PermissionInfo getPermissionInfo(String name, String packageName, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryPermissionsByGroup(String group, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getAllPermissionGroups(int flags) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ActivityInfo getActivityInfo(ComponentName className, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean activitySupportsIntent(ComponentName className, Intent intent,
-        String resolvedType)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public ActivityInfo getReceiverInfo(ComponentName className, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ProviderInfo getProviderInfo(ComponentName className, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public int checkPermission(String permName, String pkgName, int userId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int checkUidPermission(String permName, int uid) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public boolean addPermission(PermissionInfo info) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void removePermission(String name) throws RemoteException {
-
-    }
-
-    @Override
-    public void grantRuntimePermission(String packageName, String permissionName, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void revokeRuntimePermission(String packageName, String permissionName, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void resetRuntimePermissions() throws RemoteException {
-
-    }
-
-    @Override
-    public int getPermissionFlags(String permissionName, String packageName, int userId)
-        throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)
-            throws RemoteException {
-
-    }
-
-    @Override
-    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public List<String> getWhitelistedRestrictedPermissions(String packageName, int flags,
-            int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean addWhitelistedRestrictedPermission(String packageName, String permission,
-            int whitelistFlags, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean removeWhitelistedRestrictedPermission(String packageName, String permission,
-            int whitelistFlags, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean shouldShowRequestPermissionRationale(String permissionName, String packageName,
-        int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean isProtectedBroadcast(String actionName) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public int checkSignatures(String pkg1, String pkg2) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int checkUidSignatures(int uid1, int uid2) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public List<String> getAllPackages() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String[] getPackagesForUid(int uid) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public String getNameForUid(int uid) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String[] getNamesForUids(int[] uids) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public int getUidForSharedUser(String sharedUserName) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int getFlagsForUid(int uid) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int getPrivateFlagsForUid(int uid) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public boolean isUidPrivileged(int uid) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public String[] getAppOpPermissionPackages(String permissionName) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean canForwardTo(Intent intent, String resolvedType, int sourceUserId,
-        int targetUserId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public ParceledListSlice queryIntentActivities(Intent intent, String resolvedType, int flags,
-        int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryIntentActivityOptions(ComponentName caller, Intent[] specifics,
-        String[] specificTypes, Intent intent, String resolvedType, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryIntentReceivers(Intent intent, String resolvedType, int flags,
-        int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryIntentServices(Intent intent, String resolvedType, int flags,
-        int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryIntentContentProviders(Intent intent, String resolvedType,
-        int flags, int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getInstalledPackages(int flags, int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getPackagesHoldingPermissions(String[] permissions, int flags,
-        int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getInstalledApplications(int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getPersistentApplications(int flags) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ProviderInfo resolveContentProvider(String name, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public ParceledListSlice queryContentProviders(String processName, int uid, int flags,
-        String metaDataKey) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice queryInstrumentation(String targetPackage, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void finishPackageInstall(int token, boolean didLaunch) throws RemoteException {
-
-    }
-
-    @Override
-    public void setInstallerPackageName(String targetPackage, String installerPackageName)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void setApplicationCategoryHint(String packageName, int categoryHint,
-        String callerPackageName) throws RemoteException {
-
-    }
-
-    @Override
-    public void deletePackageAsUser(String packageName, int versionCode,
-        IPackageDeleteObserver observer, int userId, int flags) throws RemoteException {
-
-    }
-
-    @Override
-    public void deletePackageVersioned(VersionedPackage versionedPackage,
-        IPackageDeleteObserver2 observer, int userId, int flags) throws RemoteException {
-
-    }
-
-    @Override
-    public String getInstallerPackageName(String packageName) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void resetApplicationPreferences(int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
-        IntentFilter filter, int match, ComponentName activity) throws RemoteException {
-
-    }
-
-    @Override
-    public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set,
-        ComponentName activity, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set,
-        ComponentName activity, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void clearPackagePreferredActivities(String packageName) throws RemoteException {
-
-    }
-
-    @Override
-    public int getPreferredActivities(List<IntentFilter> outFilters,
-        List<ComponentName> outActivities, String packageName) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity,
-        int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void clearPackagePersistentPreferredActivities(String packageName, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage,
-        int sourceUserId, int targetUserId, int flags) throws RemoteException {
-
-    }
-
-    @Override
-    public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public String[] setDistractingPackageRestrictionsAsUser(String[] packageNames,
-        int restrictionFlags, int userId) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
-        PersistableBundle appExtras, PersistableBundle launcherExtras, SuspendDialogInfo dialogInfo,
-        String callingPackage, int userId) throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId)
-        throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public boolean isPackageSuspendedForUser(String packageName, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public byte[] getPreferredActivityBackup(int userId) throws RemoteException {
-        return new byte[0];
-    }
-
-    @Override
-    public void restorePreferredActivities(byte[] backup, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public byte[] getDefaultAppsBackup(int userId) throws RemoteException {
-        return new byte[0];
-    }
-
-    @Override
-    public void restoreDefaultApps(byte[] backup, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public byte[] getIntentFilterVerificationBackup(int userId) throws RemoteException {
-        return new byte[0];
-    }
-
-    @Override
-    public void restoreIntentFilterVerification(byte[] backup, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public ComponentName getHomeActivities(List<ResolveInfo> outHomeCandidates)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void setHomeActivity(ComponentName className, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags,
-        int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public int getComponentEnabledSetting(ComponentName componentName, int userId)
-        throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void setApplicationEnabledSetting(String packageName, int newState, int flags,
-        int userId,
-        String callingPackage) throws RemoteException {
-
-    }
-
-    @Override
-    public void logAppProcessStartIfNeeded(String processName, int uid, String seinfo,
-        String apkFile,
-        int pid) throws RemoteException {
-
-    }
-
-    @Override
-    public void flushPackageRestrictionsAsUser(int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void setPackageStoppedState(String packageName, boolean stopped, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void freeStorageAndNotify(String volumeUuid, long freeStorageSize, int storageFlags,
-        IPackageDataObserver observer) throws RemoteException {
-
-    }
-
-    @Override
-    public void freeStorage(String volumeUuid, long freeStorageSize, int storageFlags,
-        IntentSender pi) throws RemoteException {
-
-    }
-
-    @Override
-    public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
-        IPackageDataObserver observer) throws RemoteException {
-
-    }
-
-    @Override
-    public void clearApplicationUserData(String packageName, IPackageDataObserver observer,
-        int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void clearApplicationProfileData(String packageName) throws RemoteException {
-
-    }
-
-    @Override
-    public void getPackageSizeInfo(String packageName, int userHandle,
-        IPackageStatsObserver observer)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public String[] getSystemSharedLibraryNames() throws RemoteException {
-        return new String[0];
-    }
-
-    @Override
-    public ParceledListSlice getSystemAvailableFeatures() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean hasSystemFeature(String name, int version) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void enterSafeMode() throws RemoteException {
-
-    }
-
-    @Override
-    public boolean isSafeMode() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void systemReady() throws RemoteException {
-
-    }
-
-    @Override
-    public boolean hasSystemUidErrors() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void performFstrimIfNeeded() throws RemoteException {
-
-    }
-
-    @Override
-    public void updatePackagesIfNeeded() throws RemoteException {
-
-    }
-
-    @Override
-    public void notifyPackageUse(String packageName, int reason) throws RemoteException {
-
-    }
-
-    @Override
-    public void notifyDexLoad(String loadingPackageName, List<String> classLoadersNames,
-        List<String> classPaths, String loaderIsa) throws RemoteException {
-
-    }
-
-    @Override
-    public void registerDexModule(String packageName, String dexModulePath, boolean isSharedModule,
-        IDexModuleRegisterCallback callback) throws RemoteException {
-
-    }
-
-    @Override
-    public boolean performDexOptMode(String packageName, boolean checkProfiles,
-        String targetCompilerFilter, boolean force, boolean bootComplete, String splitName)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean performDexOptSecondary(String packageName, String targetCompilerFilter,
-        boolean force) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean compileLayouts(String packageName) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void dumpProfiles(String packageName) throws RemoteException {
-
-    }
-
-    @Override
-    public void forceDexOpt(String packageName) throws RemoteException {
-
-    }
-
-    @Override
-    public boolean runBackgroundDexoptJob(List<String> packageNames) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void reconcileSecondaryDexFiles(String packageName) throws RemoteException {
-
-    }
-
-    @Override
-    public int getMoveStatus(int moveId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void registerMoveCallback(IPackageMoveObserver callback) throws RemoteException {
-
-    }
-
-    @Override
-    public void unregisterMoveCallback(IPackageMoveObserver callback) throws RemoteException {
-
-    }
-
-    @Override
-    public int movePackage(String packageName, String volumeUuid) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int movePrimaryStorage(String volumeUuid) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public boolean addPermissionAsync(PermissionInfo info) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean setInstallLocation(int loc) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public int getInstallLocation() throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
-        int installReason) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
-
-    }
-
-    @Override
-    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
-        long millisecondsToDelay) throws RemoteException {
-
-    }
-
-    @Override
-    public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public int getIntentVerificationStatus(String packageName, int userId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public boolean updateIntentVerificationStatus(String packageName, int status, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public ParceledListSlice getIntentFilterVerifications(String packageName)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getAllIntentFilters(String packageName) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean setDefaultBrowserPackageName(String packageName, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public String getDefaultBrowserPackageName(int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean isFirstBoot() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean isOnlyCoreApps() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean isDeviceUpgrading() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void setPermissionEnforced(String permission, boolean enforced) throws RemoteException {
-
-    }
-
-    @Override
-    public boolean isPermissionEnforced(String permission) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean isStorageLow() throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean getApplicationHiddenSettingAsUser(String packageName, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public boolean setSystemAppInstallState(String packageName, boolean installed, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public IPackageInstaller getPackageInstaller() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean getBlockUninstallForUser(String packageName, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public KeySet getKeySetByAlias(String packageName, String alias) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public KeySet getSigningKeySet(String packageName) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean isPackageSignedByKeySet(String packageName, KeySet ks) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void grantDefaultPermissionsToEnabledTelephonyDataServices(String[] packageNames,
-        int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void revokeDefaultPermissionsFromDisabledTelephonyDataServices(String[] packageNames,
-        int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public String getPermissionControllerPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getInstantApps(int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public byte[] getInstantAppCookie(String packageName, int userId) throws RemoteException {
-        return new byte[0];
-    }
-
-    @Override
-    public boolean setInstantAppCookie(String packageName, byte[] cookie, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public Bitmap getInstantAppIcon(String packageName, int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean isInstantApp(String packageName, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void setUpdateAvailable(String packageName, boolean updateAvaialble)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public String getServicesSystemSharedLibraryPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getSharedSystemSharedLibraryPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ChangedPackages getChangedPackages(int sequenceNumber, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean isPackageDeviceAdminOnAnyUser(String packageName) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public int getInstallReason(String packageName, int userId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public ParceledListSlice getSharedLibraries(String packageName, int flags, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ParceledListSlice getDeclaredSharedLibraries(String packageName, int flags, int userId)
-            throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean canRequestPackageInstalls(String packageName, int userId)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void deletePreloadsFileCache() throws RemoteException {
-
-    }
-
-    @Override
-    public ComponentName getInstantAppResolverComponent() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ComponentName getInstantAppResolverSettingsComponent() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ComponentName getInstantAppInstallerComponent() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getInstantAppAndroidId(String packageName, int userId) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public IArtManager getArtManager() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public void setHarmfulAppWarning(String packageName, CharSequence warning, int userId)
-        throws RemoteException {
-
-    }
-
-    @Override
-    public CharSequence getHarmfulAppWarning(String packageName, int userId)
-        throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public boolean hasSigningCertificate(String packageName, byte[] signingCertificate, int flags)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public boolean hasUidSigningCertificate(int uid, byte[] signingCertificate, int flags)
-        throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public String getSystemTextClassifierPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getWellbeingPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getSystemCaptionsServicePackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getAttentionServicePackageName() throws RemoteException {
-        return null;
-    }
-
-    public String getIncidentReportApproverPackageName() throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public String getAppPredictionServicePackageName() {
-        return null;
-    }
-
-    @Override
-    public boolean isPackageStateProtected(String packageName, int userId) throws RemoteException {
-        return false;
-    }
-
-    @Override
-    public void sendDeviceCustomizationReadyBroadcast() throws RemoteException {
-
-    }
-
-    @Override
-    public List<ModuleInfo> getInstalledModules(int flags) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public ModuleInfo getModuleInfo(String packageName, int flags) throws RemoteException {
-        return null;
-    }
-
-    @Override
-    public int getRuntimePermissionsVersion(int userId) throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void setRuntimePermissionsVersion(int version, int userId) throws RemoteException {
-
-    }
-
-    @Override
-    public IBinder asBinder() {
-        return null;
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index a92b576..a901175 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -36,7 +37,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.backup.UserBackupManagerService;
-import com.android.server.backup.testutils.IPackageManagerStub;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -54,14 +54,12 @@
     private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
     private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
 
-    private IPackageManagerStub mPackageManagerStub;
     private PackageManagerInternal mMockPackageManagerInternal;
 
     private int mUserId;
 
     @Before
     public void setUp() throws Exception {
-        mPackageManagerStub = new IPackageManagerStub();
         mMockPackageManagerInternal = mock(PackageManagerInternal.class);
 
         mUserId = UserHandle.USER_SYSTEM;
@@ -76,7 +74,7 @@
         applicationInfo.packageName = TEST_PACKAGE_NAME;
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -91,7 +89,7 @@
         applicationInfo.packageName = TEST_PACKAGE_NAME;
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -105,7 +103,7 @@
         applicationInfo.packageName = UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -118,12 +116,11 @@
         applicationInfo.uid = Process.SYSTEM_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isTrue();
     }
@@ -136,12 +133,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = null;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isTrue();
     }
@@ -154,12 +150,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isTrue();
     }
@@ -172,12 +167,11 @@
         applicationInfo.uid = Process.SYSTEM_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -190,12 +184,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = null;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -208,12 +201,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
-
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
         boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
-                mPackageManagerStub, mUserId);
+                mMockPackageManagerInternal, mUserId);
 
         assertThat(isEligible).isFalse();
     }
@@ -226,12 +218,11 @@
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
         applicationInfo.enabled = true;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isFalse();
     }
@@ -244,12 +235,12 @@
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
         applicationInfo.enabled = false;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
 
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isTrue();
     }
@@ -261,12 +252,12 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isFalse();
     }
@@ -278,12 +269,12 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isTrue();
     }
@@ -295,12 +286,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
-
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isTrue();
     }
@@ -312,12 +302,11 @@
         applicationInfo.uid = Process.FIRST_APPLICATION_UID;
         applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
         applicationInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManagerInternal.getApplicationEnabledState(TEST_PACKAGE_NAME, mUserId))
+                .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
 
-        IPackageManagerStub.sApplicationEnabledSetting =
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
-
-        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub,
-            mUserId);
+        boolean isDisabled =
+                AppBackupUtils.appIsDisabled(applicationInfo, mMockPackageManagerInternal, mUserId);
 
         assertThat(isDisabled).isTrue();
     }
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index 5de41ea..4de00f7 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -29,6 +29,7 @@
 
 import android.attention.AttentionManagerInternal;
 import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
+import android.content.pm.PackageManager;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.SystemClock;
@@ -49,6 +50,8 @@
 public class AttentionDetectorTest extends AndroidTestCase {
 
     @Mock
+    private PackageManager mPackageManager;
+    @Mock
     private AttentionManagerInternal mAttentionManagerInternal;
     @Mock
     private Runnable mOnUserAttention;
@@ -60,6 +63,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        when(mPackageManager.getAttentionServicePackageName()).thenReturn("com.google.android.as");
+        when(mPackageManager.checkPermission(any(), any())).thenReturn(
+                PackageManager.PERMISSION_GRANTED);
         when(mAttentionManagerInternal.checkAttention(anyLong(), any()))
                 .thenReturn(true);
         mAttentionDetector = new TestableAttentionDetector();
@@ -108,6 +114,27 @@
     }
 
     @Test
+    public void testOnUserActivity_doesntCheckIfNotSufficientPermissions() {
+        when(mPackageManager.checkPermission(any(), any())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        long when = registerAttention();
+        verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
+        assertThat(mNextDimming).isEqualTo(when);
+    }
+
+    @Test
+    public void testOnUserActivity_disablesSettingIfNotSufficientPermissions() {
+        when(mPackageManager.checkPermission(any(), any())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        registerAttention();
+        boolean enabled = Settings.System.getIntForUser(getContext().getContentResolver(),
+                Settings.System.ADAPTIVE_SLEEP, 0, UserHandle.USER_CURRENT) == 1;
+        assertFalse(enabled);
+    }
+
+    @Test
     public void testOnUserActivity_doesntCrashIfNoAttentionService() {
         mAttentionManagerInternal = null;
         registerAttention();
@@ -211,6 +238,8 @@
         TestableAttentionDetector() {
             super(AttentionDetectorTest.this.mOnUserAttention, new Object());
             mAttentionManager = mAttentionManagerInternal;
+            mPackageManager = AttentionDetectorTest.this.mPackageManager;
+            mContentResolver = getContext().getContentResolver();
             mMaximumExtensionMillis = 10000L;
         }
 
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 355ff63..2d101dd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -349,6 +349,7 @@
         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
+        mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index 91d3e5e..7e3d4b4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -206,6 +206,7 @@
 
         LocalServices.removeServiceForTest(WindowManagerInternal.class);
         LocalServices.addService(WindowManagerInternal.class, mock(WindowManagerInternal.class));
+        mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
 
         mUsers = new ArrayList<>();
         mUsers.add(new UserInfo(0, "system", 0));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 08d8333..8936450 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -110,6 +110,7 @@
     private ZenModeHelper mZenModeHelperSpy;
     private Context mContext;
     private ContentResolver mContentResolver;
+    @Mock AppOpsManager mAppOps;
 
     @Before
     public void setUp() {
@@ -127,6 +128,7 @@
                     e.toString());
         }
 
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOps);
         when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
         mConditionProviders = new ConditionProviders(mContext, new UserProfiles(),
                 AppGlobals.getPackageManager());
@@ -219,10 +221,10 @@
                 Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
-        doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyInt());
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        doNothing().when(mZenModeHelperSpy).applyRestrictions(eq(false), anyBoolean(), anyInt());
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_ALARM);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_MEDIA);
     }
 
@@ -233,9 +235,9 @@
                 Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
 
         mZenModeHelperSpy.applyRestrictions();
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false,
                 AudioAttributes.USAGE_ALARM);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false,
                 AudioAttributes.USAGE_MEDIA);
     }
 
@@ -244,13 +246,13 @@
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
                 AudioAttributes.USAGE_ALARM);
 
         // Media is a catch-all that includes games
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
                 AudioAttributes.USAGE_MEDIA);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
                 AudioAttributes.USAGE_GAME);
     }
 
@@ -262,17 +264,17 @@
         mZenModeHelperSpy.applyRestrictions();
 
         // Total silence will silence alarms, media and system noises (but not vibrations)
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_ALARM);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_MEDIA);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_GAME);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_UNKNOWN);
     }
 
@@ -283,19 +285,19 @@
         mZenModeHelperSpy.applyRestrictions();
 
         // Alarms only mode will not silence alarms
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_ALARM);
 
         // Alarms only mode will not silence media
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_MEDIA);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_GAME);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_UNKNOWN);
 
         // Alarms only will silence system noises (but not vibrations)
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
     }
 
@@ -306,9 +308,9 @@
         mZenModeHelperSpy.applyRestrictions();
 
         // Alarms only mode will silence calls despite priority-mode config
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, true,
                 AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
     }
 
@@ -319,7 +321,7 @@
         mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
-        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, false,
                 AudioAttributes.USAGE_ALARM);
     }
 
@@ -334,19 +336,64 @@
         for (int usage : AudioAttributes.SDK_USAGES) {
             if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
                 // only mute audio, not vibrations
-                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true, usage,
                         AppOpsManager.OP_PLAY_AUDIO);
-                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false, usage,
                         AppOpsManager.OP_VIBRATE);
             } else {
                 boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
                         != AudioAttributes.SUPPRESSIBLE_NEVER;
-                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, shouldMute, usage);
             }
         }
     }
 
     @Test
+    public void testApplyRestrictions_whitelist_priorityOnlyMode() {
+        mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+        mZenModeHelperSpy.applyRestrictions();
+
+        for (int usage : AudioAttributes.SDK_USAGES) {
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(new String[]{PKG_O}));
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(new String[]{PKG_O}));
+        }
+    }
+
+    @Test
+    public void testApplyRestrictions_whitelist_alarmsOnlyMode() {
+        mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_ALARMS;
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+        mZenModeHelperSpy.applyRestrictions();
+
+        for (int usage : AudioAttributes.SDK_USAGES) {
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(null));
+        }
+    }
+
+    @Test
+    public void testApplyRestrictions_whitelist_totalSilenceMode() {
+        mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_NO_INTERRUPTIONS;
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
+        mZenModeHelperSpy.applyRestrictions();
+
+        for (int usage : AudioAttributes.SDK_USAGES) {
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_PLAY_AUDIO), eq(usage), anyInt(), eq(null));
+            verify(mAppOps).setRestriction(
+                    eq(AppOpsManager.OP_VIBRATE), eq(usage), anyInt(), eq(null));
+        }
+    }
+
+    @Test
     public void testZenUpgradeNotification() {
         // shows zen upgrade notification if stored settings says to shows,
         // zen has not been updated, boot is completed
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 96db38b..a7bbe6e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -87,7 +87,7 @@
         mController.doPendingActivityLaunches(resume);
 
         verify(mStarter, times(1)).startResolvedActivity(eq(activity), eq(source), eq(null),
-                eq(null), eq(startFlags), eq(resume), eq(null), eq(null), eq(null));
+                eq(null), eq(startFlags), eq(resume), eq(null), eq(null));
     }
 
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index af04858..3392bc4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -712,7 +712,6 @@
         mRecentTasks.add(mTasks.get(4));
 
         // Freeze the list
-        long freezeTime = SystemClock.elapsedRealtime();
         mRecentTasks.setFreezeTaskListReordering();
         assertTrue(mRecentTasks.isFreezeTaskListReorderingSet());
 
@@ -720,13 +719,11 @@
         mRecentTasks.add(mTasks.get(2));
         mRecentTasks.add(mTasks.get(1));
 
-        // Override the freeze timeout params to simulate the timeout (simulate the freeze at 100ms
-        // ago with a timeout of 1ms)
-        mRecentTasks.setFreezeTaskListTimeoutParams(freezeTime - 100, 1);
-
         ActivityStack stack = mTasks.get(2).getStack();
         stack.moveToFront("", mTasks.get(2));
         doReturn(stack).when(mTestService.mRootActivityContainer).getTopDisplayFocusedStack();
+
+        // Simulate the reset from the timeout
         mRecentTasks.resetFreezeTaskListReorderingOnTimeout();
         assertFalse(mRecentTasks.isFreezeTaskListReorderingSet());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 263f650..f51ce13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
@@ -44,14 +45,18 @@
     private static final int FAKE_CALLING_UID = 667;
 
     @Test
-    public void testIsAnyNonToastWindowVisibleForUid_oneToastOneNonToastBothVisible() {
+    public void testIsAnyNonToastWindowVisibleForUid_oneToastOneAppStartOneNonToastBothVisible() {
         final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
+        final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
+                FAKE_CALLING_UID);
         toastyToast.mHasSurface = true;
         app.mHasSurface = true;
+        appStart.mHasSurface = true;
 
         assertTrue(toastyToast.isVisibleNow());
         assertTrue(app.isVisibleNow());
+        assertTrue(appStart.isVisibleNow());
         assertTrue(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
     }
 
@@ -65,6 +70,16 @@
     }
 
     @Test
+    public void testIsAnyNonToastWindowVisibleForUid_onlyAppStartingVisible() {
+        final WindowState appStart = createWindow(null, TYPE_APPLICATION_STARTING, "appStarting",
+                FAKE_CALLING_UID);
+        appStart.mHasSurface = true;
+
+        assertTrue(appStart.isVisibleNow());
+        assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
+    }
+
+    @Test
     public void testIsAnyNonToastWindowVisibleForUid_aFewNonToastButNoneVisible() {
         final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar", FAKE_CALLING_UID);
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
new file mode 100644
index 0000000..cb7bff3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerMapTests.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+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.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link WindowProcessControllerMap} class.
+ *
+ * Build/Install/Run:
+ *  atest WmTests:WindowProcessControllerMapTests
+ */
+@SmallTest
+@Presubmit
+public class WindowProcessControllerMapTests extends ActivityTestsBase {
+
+    private static final int FAKE_UID1 = 666;
+    private static final int FAKE_UID2 = 667;
+    private static final int FAKE_PID1 = 668;
+    private static final int FAKE_PID2 = 669;
+    private static final int FAKE_PID3 = 670;
+    private static final int FAKE_PID4 = 671;
+
+    private WindowProcessControllerMap mProcessMap;
+    private WindowProcessController pid1uid1;
+    private WindowProcessController pid1uid2;
+    private WindowProcessController pid2uid1;
+    private WindowProcessController pid3uid1;
+    private WindowProcessController pid4uid2;
+
+    @Before
+    public void setUp() throws Exception {
+        mProcessMap = new WindowProcessControllerMap();
+        pid1uid1 = new WindowProcessController(
+                mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid1", FAKE_UID1,
+                UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+        pid1uid1.setPid(FAKE_PID1);
+        pid1uid2 = new WindowProcessController(
+                mService, mService.mContext.getApplicationInfo(), "fakepid1fakeuid2", FAKE_UID2,
+                UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+        pid1uid2.setPid(FAKE_PID1);
+        pid2uid1 = new WindowProcessController(
+                mService, mService.mContext.getApplicationInfo(), "fakepid2fakeuid1", FAKE_UID1,
+                UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+        pid2uid1.setPid(FAKE_PID2);
+        pid3uid1 = new WindowProcessController(
+                mService, mService.mContext.getApplicationInfo(), "fakepid3fakeuid1", FAKE_UID1,
+                UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+        pid3uid1.setPid(FAKE_PID3);
+        pid4uid2 = new WindowProcessController(
+                mService, mService.mContext.getApplicationInfo(), "fakepid4fakeuid2", FAKE_UID2,
+                UserHandle.getUserId(12345), mock(Object.class), mock(WindowProcessListener.class));
+        pid4uid2.setPid(FAKE_PID4);
+    }
+
+    @Test
+    public void testAdditionsAndRemovals() {
+        // test various additions and removals
+        mProcessMap.put(FAKE_PID1, pid1uid1);
+        mProcessMap.put(FAKE_PID2, pid2uid1);
+        assertEquals(pid1uid1, mProcessMap.getProcess(FAKE_PID1));
+        assertEquals(pid2uid1, mProcessMap.getProcess(FAKE_PID2));
+        ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+        assertTrue(uid1processes.contains(pid1uid1));
+        assertTrue(uid1processes.contains(pid2uid1));
+        assertEquals(uid1processes.size(), 2);
+
+        mProcessMap.remove(FAKE_PID2);
+        mProcessMap.put(FAKE_PID3, pid3uid1);
+        uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+        assertTrue(uid1processes.contains(pid1uid1));
+        assertFalse(uid1processes.contains(pid2uid1));
+        assertTrue(uid1processes.contains(pid3uid1));
+        assertEquals(uid1processes.size(), 2);
+
+        mProcessMap.put(FAKE_PID4, pid4uid2);
+        ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+        assertTrue(uid2processes.contains(pid4uid2));
+        assertEquals(uid2processes.size(), 1);
+
+        mProcessMap.remove(FAKE_PID1);
+        mProcessMap.remove(FAKE_PID3);
+        assertNull(mProcessMap.getProcesses(FAKE_UID1));
+        assertEquals(mProcessMap.getProcess(FAKE_PID4), pid4uid2);
+    }
+
+    @Test
+    public void testReplacement() {
+        // test that replacing a process is handled correctly
+        mProcessMap.put(FAKE_PID1, pid1uid1);
+        ArraySet<WindowProcessController> uid1processes = mProcessMap.getProcesses(FAKE_UID1);
+        assertTrue(uid1processes.contains(pid1uid1));
+        assertEquals(uid1processes.size(), 1);
+
+        mProcessMap.put(FAKE_PID1, pid1uid2);
+        assertNull(mProcessMap.getProcesses(FAKE_UID1));
+        ArraySet<WindowProcessController> uid2processes = mProcessMap.getProcesses(FAKE_UID2);
+        assertTrue(uid2processes.contains(pid1uid2));
+        assertEquals(uid2processes.size(), 1);
+        assertEquals(mProcessMap.getProcess(FAKE_PID1), pid1uid2);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 4f8fe5b..715353e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -397,7 +397,9 @@
         app.mLayoutSeq = 1;
         mDisplayContent.mLayoutSeq = 1;
 
-        app.onDisplayChanged(mDisplayContent);
+        DisplayContent newDisplay = createNewDisplay();
+
+        app.onDisplayChanged(newDisplay);
 
         assertThat(app.mLayoutSeq, not(is(mDisplayContent.mLayoutSeq)));
     }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 79e6851..5b7d816 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1095,6 +1095,14 @@
                     Slog.d(TAG, "Clear notification");
                     mUsbNotificationId = 0;
                 }
+                // Not relevant for automotive.
+                if (mContext.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_AUTOMOTIVE)
+                        && id == SystemMessage.NOTE_USB_CHARGING) {
+                    mUsbNotificationId = 0;
+                    return;
+                }
+
                 if (id != 0) {
                     CharSequence title = r.getText(titleRes);
                     PendingIntent pi;
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 71a28b5..eb568e0 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.os.Build;
@@ -174,4 +175,21 @@
                 in.readString(),
                 UserHandle.CREATOR.createFromParcel(in));
     }
+
+    /**
+     * Determines if two {@link PhoneAccountHandle}s are from the same package.
+     *
+     * @param a Phone account handle to check for same {@link ConnectionService} package.
+     * @param b Other phone account handle to check for same {@link ConnectionService} package.
+     * @return {@code true} if the two {@link PhoneAccountHandle}s passed in belong to the same
+     * {@link ConnectionService} / package, {@code false} otherwise.  Note: {@code null} phone
+     * account handles are considered equivalent to other {@code null} phone account handles.
+     * @hide
+     */
+    public static boolean areFromSamePackage(@Nullable PhoneAccountHandle a,
+            @Nullable PhoneAccountHandle b) {
+        String aPackageName = a != null ? a.getComponentName().getPackageName() : null;
+        String bPackageName = b != null ? b.getComponentName().getPackageName() : null;
+        return Objects.equals(aPackageName, bPackageName);
+    }
 }
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index cf15b92..c57f9e6 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -39,6 +39,7 @@
 import android.util.Log;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -123,6 +124,16 @@
     private String mMnc;
 
     /**
+     * EHPLMNs associated with the subscription
+     */
+    private String[] mEhplmns;
+
+    /**
+     * HPLMNs associated with the subscription
+     */
+    private String[] mHplmns;
+
+    /**
      * ISO Country code for the subscription's provider
      */
     private String mCountryIso;
@@ -316,6 +327,14 @@
     }
 
     /**
+     * @hide
+     */
+    public void setAssociatedPlmns(String[] ehplmns, String[] hplmns) {
+        mEhplmns = ehplmns;
+        mHplmns = hplmns;
+    }
+
+    /**
      * Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a
      * user interface.
      *
@@ -467,6 +486,20 @@
     }
 
     /**
+     * @hide
+     */
+    public List<String> getEhplmns() {
+        return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns);
+    }
+
+    /**
+     * @hide
+     */
+    public List<String> getHplmns() {
+        return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns);
+    }
+
+    /**
      * @return the profile class of this subscription.
      * @hide
      */
@@ -600,7 +633,7 @@
             String mcc = source.readString();
             String mnc = source.readString();
             String countryIso = source.readString();
-            Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
+            Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
             boolean isEmbedded = source.readBoolean();
             UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
             String cardString = source.readString();
@@ -611,11 +644,15 @@
             int carrierid = source.readInt();
             int profileClass = source.readInt();
             int subType = source.readInt();
+            String[] ehplmns = source.readStringArray();
+            String[] hplmns = source.readStringArray();
 
-            return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
-                    nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
-                    isEmbedded, accessRules, cardString, cardId, isOpportunistic, groupUUID,
-                    isGroupDisabled, carrierid, profileClass, subType);
+            SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
+                    carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
+                    countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
+                    groupUUID, isGroupDisabled, carrierid, profileClass, subType);
+            info.setAssociatedPlmns(ehplmns, hplmns);
+            return info;
         }
 
         @Override
@@ -638,7 +675,7 @@
         dest.writeString(mMcc);
         dest.writeString(mMnc);
         dest.writeString(mCountryIso);
-        mIconBitmap.writeToParcel(dest, flags);
+        dest.writeParcelable(mIconBitmap, flags);
         dest.writeBoolean(mIsEmbedded);
         dest.writeTypedArray(mAccessRules, flags);
         dest.writeString(mCardString);
@@ -649,6 +686,8 @@
         dest.writeInt(mCarrierId);
         dest.writeInt(mProfileClass);
         dest.writeInt(mSubscriptionType);
+        dest.writeStringArray(mEhplmns);
+        dest.writeStringArray(mHplmns);
     }
 
     @Override
@@ -686,6 +725,8 @@
                 + " isOpportunistic " + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
                 + " mIsGroupDisabled=" + mIsGroupDisabled
                 + " profileClass=" + mProfileClass
+                + " ehplmns = " + Arrays.toString(mEhplmns)
+                + " hplmns = " + Arrays.toString(mHplmns)
                 + " subscriptionType=" + mSubscriptionType + "}";
     }
 
@@ -729,6 +770,8 @@
                 && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
                 && TextUtils.equals(mCarrierName, toCompare.mCarrierName)
                 && Arrays.equals(mAccessRules, toCompare.mAccessRules)
-                && mProfileClass == toCompare.mProfileClass;
+                && mProfileClass == toCompare.mProfileClass
+                && Arrays.equals(mEhplmns, toCompare.mEhplmns)
+                && Arrays.equals(mHplmns, toCompare.mHplmns);
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0c63411..0808adf 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -458,6 +458,18 @@
     public static final String CARRIER_ID = "carrier_id";
 
     /**
+     * @hide A comma-separated list of EHPLMNs associated with the subscription
+     * <P>Type: TEXT (String)</P>
+     */
+    public static final String EHPLMNS = "ehplmns";
+
+    /**
+     * @hide A comma-separated list of HPLMNs associated with the subscription
+     * <P>Type: TEXT (String)</P>
+     */
+    public static final String HPLMNS = "hplmns";
+
+    /**
      * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
      * <P>Type: TEXT (String)</P>
      * @hide
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index e8fcac1..de4f174 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.content.Intent;
 import android.os.IInterface;
 import android.os.RemoteException;
 import android.telephony.SubscriptionManager;
@@ -42,32 +41,6 @@
 
     private static final String LOG_TAG = "ImsFeature";
 
-    /**
-     * Action to broadcast when ImsService is up.
-     * Internal use only.
-     * Only defined here separately compatibility purposes with the old ImsService.
-     * @hide
-     */
-    public static final String ACTION_IMS_SERVICE_UP =
-            "com.android.ims.IMS_SERVICE_UP";
-
-    /**
-     * Action to broadcast when ImsService is down.
-     * Internal use only.
-     * Only defined here separately for compatibility purposes with the old ImsService.
-     * @hide
-     */
-    public static final String ACTION_IMS_SERVICE_DOWN =
-            "com.android.ims.IMS_SERVICE_DOWN";
-
-    /**
-     * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents.
-     * A long value; the phone ID corresponding to the IMS service coming up or down.
-     * Only defined here separately for compatibility purposes with the old ImsService.
-     * @hide
-     */
-    public static final String EXTRA_PHONE_ID = "android:phone_id";
-
     // Invalid feature value
     public static final int INVALID = -1;
     // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously
@@ -162,30 +135,6 @@
                 }
             }
         }
-        sendImsServiceIntent(state);
-    }
-
-    /**
-     * Provide backwards compatibility using deprecated service UP/DOWN intents.
-     */
-    private void sendImsServiceIntent(@ImsState int state) {
-        if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-            return;
-        }
-        Intent intent;
-        switch (state) {
-            case ImsFeature.STATE_NOT_AVAILABLE:
-            case ImsFeature.STATE_INITIALIZING:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-                break;
-            case ImsFeature.STATE_READY:
-                intent = new Intent(ACTION_IMS_SERVICE_UP);
-                break;
-            default:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-        }
-        intent.putExtra(EXTRA_PHONE_ID, mSlotId);
-        mContext.sendBroadcast(intent);
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 5e3f398..74af6bf 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.content.Intent;
 import android.os.IInterface;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -395,30 +394,6 @@
                 }
             }
         }
-        sendImsServiceIntent(state);
-    }
-
-    /**
-     * Provide backwards compatibility using deprecated service UP/DOWN intents.
-     */
-    private void sendImsServiceIntent(@ImsState int state) {
-        if (mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-            return;
-        }
-        Intent intent;
-        switch (state) {
-            case ImsFeature.STATE_UNAVAILABLE:
-            case ImsFeature.STATE_INITIALIZING:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-                break;
-            case ImsFeature.STATE_READY:
-                intent = new Intent(ACTION_IMS_SERVICE_UP);
-                break;
-            default:
-                intent = new Intent(ACTION_IMS_SERVICE_DOWN);
-        }
-        intent.putExtra(EXTRA_PHONE_ID, mSlotId);
-        mContext.sendBroadcast(intent);
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 80fb58d..12b20ef 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -344,10 +344,22 @@
             return true;
         }
         // if the calling package is null then return now as there's no way to perform the
-        // DevicePolicyManager device / profile owner checks.
+        // DevicePolicyManager device / profile owner and AppOp checks
         if (callingPackage == null) {
             return false;
         }
+        // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
+        long token = Binder.clearCallingIdentity();
+        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
+                Context.APP_OPS_SERVICE);
+        try {
+            if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
+                    callingPackage) == AppOpsManager.MODE_ALLOWED) {
+                return true;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
         // Allow access to a device / profile owner app.
         DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
diff --git a/tests/FlickerTests/lib/Android.bp b/tests/FlickerTests/lib/Android.bp
index 982fcba..5d8ed2c 100644
--- a/tests/FlickerTests/lib/Android.bp
+++ b/tests/FlickerTests/lib/Android.bp
@@ -20,7 +20,7 @@
     srcs: ["src/**/*.java"],
     static_libs: [
         "androidx.test.janktesthelper",
-        "cts-amwm-util",
+        "cts-wm-util",
         "platformprotosnano",
         "layersprotosnano",
         "truth-prebuilt",
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index e0d74e0..c9e3404 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -34,6 +34,8 @@
 public final class FrameworksTestsFilter extends SelectTest {
 
     private static final String[] SELECTED_TESTS = {
+            // Test specifications for FrameworksMockingCoreTests.
+            "android.app.activity.ActivityThreadClientTest",
             // Test specifications for FrameworksCoreTests.
             "android.app.servertransaction.", // all tests under the package.
             "android.view.DisplayCutoutTest",
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 9832485..3da22b4 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -129,12 +129,20 @@
     constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS;
     if (attr->type_mask & kMask) {
       for (const auto& symbol : attr->symbols) {
-        printer_->Print(symbol.symbol.name.value().entry);
-        if (symbol.symbol.id) {
-          printer_->Print("(");
+        if (symbol.symbol.name) {
+          printer_->Print(symbol.symbol.name.value().entry);
+
+          if (symbol.symbol.id) {
+            printer_->Print("(");
+            printer_->Print(symbol.symbol.id.value().to_string());
+            printer_->Print(")");
+          }
+        } else if (symbol.symbol.id) {
           printer_->Print(symbol.symbol.id.value().to_string());
-          printer_->Print(")");
+        } else {
+          printer_->Print("???");
         }
+
         printer_->Println(StringPrintf("=0x%08x", symbol.value));
       }
     }
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 950c6f8..9d4b837 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -967,6 +967,10 @@
      * from the top-level domain and all the labels in domain_suffix_match shall be included in the
      * certificate. The certificate may include additional sub-level labels in addition to the
      * required labels.
+     * <p>More than one match string can be provided by using semicolons to separate the strings
+     * (e.g., example.org;example.com). When multiple strings are specified, a match with any one of
+     * the values is considered a sufficient match for the certificate, i.e., the conditions are
+     * ORed ogether.
      * <p>For example, domain_suffix_match=example.com would match test.example.com but would not
      * match test-example.com.
      * @param domain The domain value