Merge "Return null when getting role holders of an unknown role."
diff --git a/Android.bp b/Android.bp
index 7e97e66..c202408 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1067,6 +1067,7 @@
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/NonNull.java",
         "core/java/android/annotation/SystemApi.java",
+        "core/java/android/annotation/TestApi.java",
         "core/java/android/os/HwBinder.java",
         "core/java/android/os/HwBlob.java",
         "core/java/android/os/HwParcel.java",
diff --git a/api/current.txt b/api/current.txt
index 80fea7b..18f150f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11191,6 +11191,7 @@
     method public void registerCallback(android.content.pm.LauncherApps.Callback);
     method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
+    method public boolean shouldHideFromSuggestions(java.lang.String, android.os.UserHandle);
     method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
     method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
@@ -13736,6 +13737,7 @@
     method public void drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint);
     method public void drawTextRun(char[], int, int, int, int, float, float, boolean, android.graphics.Paint);
     method public void drawTextRun(java.lang.CharSequence, int, int, int, int, float, float, boolean, android.graphics.Paint);
+    method public void drawTextRun(android.graphics.text.MeasuredText, int, int, int, int, float, float, boolean, android.graphics.Paint);
     method public void drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint);
     method public void enableZ();
     method public boolean getClipBounds(android.graphics.Rect);
@@ -22662,6 +22664,7 @@
     method public deprecated double getCarrierPhase();
     method public deprecated double getCarrierPhaseUncertainty();
     method public double getCn0DbHz();
+    method public int getCodeType();
     method public int getConstellationType();
     method public int getMultipathIndicator();
     method public double getPseudorangeRateMetersPerSecond();
@@ -22677,6 +22680,7 @@
     method public boolean hasCarrierFrequencyHz();
     method public deprecated boolean hasCarrierPhase();
     method public deprecated boolean hasCarrierPhaseUncertainty();
+    method public boolean hasCodeType();
     method public boolean hasSnrInDb();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
@@ -22685,6 +22689,21 @@
     field public static final int ADR_STATE_RESET = 2; // 0x2
     field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
     field public static final int ADR_STATE_VALID = 1; // 0x1
+    field public static final int CODE_TYPE_A = 0; // 0x0
+    field public static final int CODE_TYPE_B = 1; // 0x1
+    field public static final int CODE_TYPE_C = 2; // 0x2
+    field public static final int CODE_TYPE_CODELESS = 13; // 0xd
+    field public static final int CODE_TYPE_I = 3; // 0x3
+    field public static final int CODE_TYPE_L = 4; // 0x4
+    field public static final int CODE_TYPE_M = 5; // 0x5
+    field public static final int CODE_TYPE_P = 6; // 0x6
+    field public static final int CODE_TYPE_Q = 7; // 0x7
+    field public static final int CODE_TYPE_S = 8; // 0x8
+    field public static final int CODE_TYPE_UNKNOWN = -1; // 0xffffffff
+    field public static final int CODE_TYPE_W = 9; // 0x9
+    field public static final int CODE_TYPE_X = 10; // 0xa
+    field public static final int CODE_TYPE_Y = 11; // 0xb
+    field public static final int CODE_TYPE_Z = 12; // 0xc
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
     field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
     field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
@@ -24175,8 +24194,11 @@
   public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
     ctor public MediaCodec.CryptoException(int, java.lang.String);
     method public int getErrorCode();
+    field public static final int ERROR_FRAME_TOO_LARGE = 8; // 0x8
     field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
+    field public static final int ERROR_INSUFFICIENT_SECURITY = 7; // 0x7
     field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
+    field public static final int ERROR_LOST_STATE = 9; // 0x9
     field public static final int ERROR_NO_KEY = 1; // 0x1
     field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
     field public static final int ERROR_SESSION_NOT_OPENED = 5; // 0x5
@@ -24517,6 +24539,22 @@
     field public static final int REGULAR_CODECS = 0; // 0x0
   }
 
+  public class MediaController2 implements java.lang.AutoCloseable {
+    ctor public MediaController2(android.content.Context, android.media.Session2Token);
+    ctor public MediaController2(android.content.Context, android.media.Session2Token, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback);
+    method public void cancelSessionCommand(java.lang.Object);
+    method public void close();
+    method public java.lang.Object sendSessionCommand(android.media.Session2Command, android.os.Bundle);
+  }
+
+  public static abstract class MediaController2.ControllerCallback {
+    ctor public MediaController2.ControllerCallback();
+    method public void onCommandResult(android.media.MediaController2, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result);
+    method public void onConnected(android.media.MediaController2, android.media.Session2CommandGroup);
+    method public void onDisconnected(android.media.MediaController2);
+    method public android.media.Session2Command.Result onSessionCommand(android.media.MediaController2, android.media.Session2Command, android.os.Bundle);
+  }
+
   public final class MediaCrypto {
     ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
     method protected void finalize();
@@ -24624,6 +24662,7 @@
     method public void setOnEventListener(android.media.MediaDrm.OnEventListener);
     method public void setOnExpirationUpdateListener(android.media.MediaDrm.OnExpirationUpdateListener, android.os.Handler);
     method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
+    method public void setOnSessionLostStateListener(android.media.MediaDrm.OnSessionLostStateListener, android.os.Handler);
     method public void setPropertyByteArray(java.lang.String, byte[]);
     method public void setPropertyString(java.lang.String, java.lang.String);
     field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
@@ -24742,6 +24781,10 @@
     method public abstract void onKeyStatusChange(android.media.MediaDrm, byte[], java.util.List<android.media.MediaDrm.KeyStatus>, boolean);
   }
 
+  public static abstract interface MediaDrm.OnSessionLostStateListener {
+    method public abstract void onSessionLostState(android.media.MediaDrm, byte[]);
+  }
+
   public static final class MediaDrm.ProvisionRequest {
     method public byte[] getData();
     method public java.lang.String getDefaultUrl();
@@ -24750,6 +24793,12 @@
   public static abstract class MediaDrm.SecurityLevel implements java.lang.annotation.Annotation {
   }
 
+  public static final class MediaDrm.SessionException extends java.lang.RuntimeException {
+    ctor public MediaDrm.SessionException(int, java.lang.String);
+    method public int getErrorCode();
+    field public static final int ERROR_RESOURCE_CONTENTION = 1; // 0x1
+  }
+
   public class MediaDrmException extends java.lang.Exception {
     ctor public MediaDrmException(java.lang.String);
   }
@@ -25805,6 +25854,37 @@
     method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
   }
 
+  public class MediaSession2 implements java.lang.AutoCloseable {
+    method public void broadcastSessionCommand(android.media.Session2Command, android.os.Bundle);
+    method public void cancelSessionCommand(android.media.MediaSession2.ControllerInfo, java.lang.Object);
+    method public void close();
+    method public java.lang.String getSessionId();
+    method public android.media.Session2Token getSessionToken();
+    method public java.lang.Object sendSessionCommand(android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle);
+  }
+
+  public static final class MediaSession2.Builder {
+    ctor public MediaSession2.Builder(android.content.Context);
+    method public android.media.MediaSession2 build();
+    method public android.media.MediaSession2.Builder setId(java.lang.String);
+    method public android.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent);
+    method public android.media.MediaSession2.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaSession2.SessionCallback);
+  }
+
+  public static final class MediaSession2.ControllerInfo {
+    method public java.lang.String getPackageName();
+    method public android.media.session.MediaSessionManager.RemoteUserInfo getRemoteUserInfo();
+    method public int getUid();
+  }
+
+  public static abstract class MediaSession2.SessionCallback {
+    ctor public MediaSession2.SessionCallback();
+    method public void onCommandResult(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result);
+    method public android.media.Session2CommandGroup onConnect(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo);
+    method public void onDisconnected(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo);
+    method public android.media.Session2Command.Result onSessionCommand(android.media.MediaSession2, android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle);
+  }
+
   public final class MediaSync {
     ctor public MediaSync();
     method public android.view.Surface createInputSurface();
@@ -26118,6 +26198,19 @@
     method public android.media.Session2CommandGroup.Builder removeCommand(int);
   }
 
+  public final class Session2Token implements android.os.Parcelable {
+    ctor public Session2Token(android.content.Context, android.content.ComponentName);
+    method public int describeContents();
+    method public java.lang.String getPackageName();
+    method public java.lang.String getServiceName();
+    method public int getType();
+    method public int getUid();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.media.Session2Token> CREATOR;
+    field public static final int TYPE_SESSION = 0; // 0x0
+    field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+  }
+
   public class SoundPool {
     ctor public deprecated SoundPool(int, int, int);
     method public final void autoPause();
@@ -29649,8 +29742,10 @@
     method public java.lang.String getMacAddress();
     method public int getNetworkId();
     method public int getRssi();
+    method public int getRxLinkSpeedMbps();
     method public java.lang.String getSSID();
     method public android.net.wifi.SupplicantState getSupplicantState();
+    method public int getTxLinkSpeedMbps();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String FREQUENCY_UNITS = "MHz";
     field public static final java.lang.String LINK_SPEED_UNITS = "Mbps";
@@ -43057,10 +43152,12 @@
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
     field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
     field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+    field public static final java.lang.String EVENT_RTT_AUDIO_INDICATION_CHANGED = "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED";
     field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
     field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
+    field public static final java.lang.String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final java.lang.String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
@@ -45001,6 +45098,7 @@
   }
 
   public class EuiccManager {
+    method public android.telephony.euicc.EuiccManager createForCardId(int);
     method public void deleteSubscription(int, android.app.PendingIntent);
     method public void downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent);
     method public java.lang.String getEid();
@@ -47003,7 +47101,7 @@
   public class Linkify {
     ctor public Linkify();
     method public static final boolean addLinks(android.text.Spannable, int);
-    method public static final boolean addLinks(android.text.Spannable, int, android.text.util.Linkify.UrlSpanFactory);
+    method public static final boolean addLinks(android.text.Spannable, int, java.util.function.Function<java.lang.String, android.text.style.URLSpan>);
     method public static final boolean addLinks(android.widget.TextView, int);
     method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String);
     method public static final void addLinks(android.widget.TextView, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
@@ -47011,7 +47109,7 @@
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String);
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
     method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
-    method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter, android.text.util.Linkify.UrlSpanFactory);
+    method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter, java.util.function.Function<java.lang.String, android.text.style.URLSpan>);
     field public static final int ALL = 15; // 0xf
     field public static final int EMAIL_ADDRESSES = 2; // 0x2
     field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
@@ -47030,11 +47128,6 @@
     method public abstract java.lang.String transformUrl(java.util.regex.Matcher, java.lang.String);
   }
 
-  public static class Linkify.UrlSpanFactory {
-    ctor public Linkify.UrlSpanFactory();
-    method public android.text.style.URLSpan create(java.lang.String);
-  }
-
   public class Rfc822Token {
     ctor public Rfc822Token(java.lang.String, java.lang.String, java.lang.String);
     method public java.lang.String getAddress();
@@ -52938,15 +53031,15 @@
 
 package android.view.textclassifier {
 
-  public final class ConversationActions implements android.os.Parcelable {
-    ctor public ConversationActions(java.util.List<android.view.textclassifier.ConversationActions.ConversationAction>, java.lang.String);
+  public final class ConversationAction implements android.os.Parcelable {
     method public int describeContents();
-    method public java.util.List<android.view.textclassifier.ConversationActions.ConversationAction> getConversationActions();
-    method public java.lang.String getId();
+    method public android.app.RemoteAction getAction();
+    method public float getConfidenceScore();
+    method public android.os.Bundle getExtras();
+    method public java.lang.CharSequence getTextReply();
+    method public java.lang.String getType();
     method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions> CREATOR;
-    field public static final java.lang.String HINT_FOR_IN_APP = "in_app";
-    field public static final java.lang.String HINT_FOR_NOTIFICATION = "notification";
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationAction> CREATOR;
     field public static final java.lang.String TYPE_CALL_PHONE = "call_phone";
     field public static final java.lang.String TYPE_CREATE_REMINDER = "create_reminder";
     field public static final java.lang.String TYPE_OPEN_URL = "open_url";
@@ -52959,24 +53052,22 @@
     field public static final java.lang.String TYPE_VIEW_MAP = "view_map";
   }
 
-  public static final class ConversationActions.ConversationAction implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.app.RemoteAction getAction();
-    method public float getConfidenceScore();
-    method public android.os.Bundle getExtras();
-    method public java.lang.CharSequence getTextReply();
-    method public java.lang.String getType();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.ConversationAction> CREATOR;
+  public static final class ConversationAction.Builder {
+    ctor public ConversationAction.Builder(java.lang.String);
+    method public android.view.textclassifier.ConversationAction build();
+    method public android.view.textclassifier.ConversationAction.Builder setAction(android.app.RemoteAction);
+    method public android.view.textclassifier.ConversationAction.Builder setConfidenceScore(float);
+    method public android.view.textclassifier.ConversationAction.Builder setExtras(android.os.Bundle);
+    method public android.view.textclassifier.ConversationAction.Builder setTextReply(java.lang.CharSequence);
   }
 
-  public static final class ConversationActions.ConversationAction.Builder {
-    ctor public ConversationActions.ConversationAction.Builder(java.lang.String);
-    method public android.view.textclassifier.ConversationActions.ConversationAction build();
-    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setAction(android.app.RemoteAction);
-    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setConfidenceScore(float);
-    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setExtras(android.os.Bundle);
-    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setTextReply(java.lang.CharSequence);
+  public final class ConversationActions implements android.os.Parcelable {
+    ctor public ConversationActions(java.util.List<android.view.textclassifier.ConversationAction>, java.lang.String);
+    method public int describeContents();
+    method public java.util.List<android.view.textclassifier.ConversationAction> getConversationActions();
+    method public java.lang.String getId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions> CREATOR;
   }
 
   public static final class ConversationActions.Message implements android.os.Parcelable {
@@ -53006,9 +53097,11 @@
     method public java.lang.String getConversationId();
     method public java.util.List<java.lang.String> getHints();
     method public int getMaxSuggestions();
-    method public android.view.textclassifier.ConversationActions.TypeConfig getTypeConfig();
+    method public android.view.textclassifier.TextClassifier.EntityConfig getTypeConfig();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Request> CREATOR;
+    field public static final java.lang.String HINT_FOR_IN_APP = "in_app";
+    field public static final java.lang.String HINT_FOR_NOTIFICATION = "notification";
   }
 
   public static final class ConversationActions.Request.Builder {
@@ -53017,23 +53110,7 @@
     method public android.view.textclassifier.ConversationActions.Request.Builder setConversationId(java.lang.String);
     method public android.view.textclassifier.ConversationActions.Request.Builder setHints(java.util.List<java.lang.String>);
     method public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(int);
-    method public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(android.view.textclassifier.ConversationActions.TypeConfig);
-  }
-
-  public static final class ConversationActions.TypeConfig implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.util.Collection<java.lang.String> resolveTypes(java.util.Collection<java.lang.String>);
-    method public boolean shouldIncludeTypesFromTextClassifier();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.TypeConfig> CREATOR;
-  }
-
-  public static final class ConversationActions.TypeConfig.Builder {
-    ctor public ConversationActions.TypeConfig.Builder();
-    method public android.view.textclassifier.ConversationActions.TypeConfig build();
-    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder includeTypesFromTextClassifier(boolean);
-    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder setExcludedTypes(java.util.Collection<java.lang.String>);
-    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder setIncludedTypes(java.util.Collection<java.lang.String>);
+    method public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(android.view.textclassifier.TextClassifier.EntityConfig);
   }
 
   public final class SelectionEvent implements android.os.Parcelable {
@@ -53207,16 +53284,26 @@
   }
 
   public static final class TextClassifier.EntityConfig implements android.os.Parcelable {
-    method public static android.view.textclassifier.TextClassifier.EntityConfig create(java.util.Collection<java.lang.String>, java.util.Collection<java.lang.String>, java.util.Collection<java.lang.String>);
-    method public static android.view.textclassifier.TextClassifier.EntityConfig createWithExplicitEntityList(java.util.Collection<java.lang.String>);
-    method public static android.view.textclassifier.TextClassifier.EntityConfig createWithHints(java.util.Collection<java.lang.String>);
+    method public static deprecated android.view.textclassifier.TextClassifier.EntityConfig create(java.util.Collection<java.lang.String>, java.util.Collection<java.lang.String>, java.util.Collection<java.lang.String>);
+    method public static deprecated android.view.textclassifier.TextClassifier.EntityConfig createWithExplicitEntityList(java.util.Collection<java.lang.String>);
+    method public static deprecated android.view.textclassifier.TextClassifier.EntityConfig createWithHints(java.util.Collection<java.lang.String>);
     method public int describeContents();
     method public java.util.Collection<java.lang.String> getHints();
     method public java.util.Collection<java.lang.String> resolveEntityListModifications(java.util.Collection<java.lang.String>);
+    method public boolean shouldIncludeTypesFromTextClassifier();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextClassifier.EntityConfig> CREATOR;
   }
 
+  public static final class TextClassifier.EntityConfig.Builder {
+    ctor public TextClassifier.EntityConfig.Builder();
+    method public android.view.textclassifier.TextClassifier.EntityConfig build();
+    method public android.view.textclassifier.TextClassifier.EntityConfig.Builder includeTypesFromTextClassifier(boolean);
+    method public android.view.textclassifier.TextClassifier.EntityConfig.Builder setExcludedTypes(java.util.Collection<java.lang.String>);
+    method public android.view.textclassifier.TextClassifier.EntityConfig.Builder setHints(java.util.Collection<java.lang.String>);
+    method public android.view.textclassifier.TextClassifier.EntityConfig.Builder setIncludedTypes(java.util.Collection<java.lang.String>);
+  }
+
   public final class TextClassifierEvent implements android.os.Parcelable {
     method public int describeContents();
     method public int[] getActionIndices();
diff --git a/api/system-current.txt b/api/system-current.txt
index 6c764b4..78f3471 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1047,7 +1047,6 @@
     method public void removeRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback);
     method public boolean removeRoleHolderFromController(java.lang.String, java.lang.String);
     method public void setRoleNamesFromController(java.util.List<java.lang.String>);
-    field public static final java.lang.String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME";
   }
 
   public abstract interface RoleManagerCallback {
@@ -1254,6 +1253,7 @@
     field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
     field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
     field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
+    field public static final java.lang.String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
     field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
     field public static final java.lang.String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
@@ -1284,11 +1284,12 @@
     field public static final java.lang.String EXTRA_LONG_VERSION_CODE = "android.intent.extra.LONG_VERSION_CODE";
     field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
     field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
-    field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
     field public static final java.lang.String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME";
+    field public static final java.lang.String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
     field public static final java.lang.String EXTRA_REASON = "android.intent.extra.REASON";
     field public static final java.lang.String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
     field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
+    field public static final java.lang.String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
     field public static final java.lang.String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
     field public static final java.lang.String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
     field public static final java.lang.String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
@@ -1461,6 +1462,7 @@
     method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public void sendDeviceCustomizationReadyBroadcast();
     method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
+    method public java.lang.String[] setDistractingPackageRestrictions(java.lang.String[], int);
     method public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence);
     method public deprecated java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String);
     method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo);
@@ -1528,6 +1530,9 @@
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
+    field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
+    field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
+    field public static final int RESTRICTION_NONE = 0; // 0x0
   }
 
   public static abstract class PackageManager.DexModuleRegisterCallback {
@@ -1535,6 +1540,9 @@
     method public abstract void onDexModuleRegistered(java.lang.String, boolean, java.lang.String);
   }
 
+  public static abstract class PackageManager.DistractionRestriction implements java.lang.annotation.Annotation {
+  }
+
   public static abstract interface PackageManager.OnPermissionsChangedListener {
     method public abstract void onPermissionsChanged(int);
   }
@@ -7243,6 +7251,7 @@
     method public void callSessionInviteParticipantsRequestDelivered();
     method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionMayHandover(int, int);
+    method public void callSessionRttAudioIndicatorChanged(android.telephony.ims.ImsStreamMediaProfile);
     method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
     method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
@@ -7660,10 +7669,12 @@
     method public int describeContents();
     method public int getAudioDirection();
     method public int getAudioQuality();
+    method public boolean getRttAudioSpeech();
     method public int getRttMode();
     method public int getVideoDirection();
     method public int getVideoQuality();
     method public boolean isRttCall();
+    method public void setRttAudioSpeech(boolean);
     method public void setRttMode(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index 6d40e69..fb50fa19 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -421,6 +421,7 @@
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
+    field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
     field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
@@ -500,6 +501,10 @@
 
 package android.graphics {
 
+  public final class Bitmap implements android.os.Parcelable {
+    method public void eraseColor(long);
+  }
+
   public final class ImageDecoder implements java.lang.AutoCloseable {
     method public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, java.io.InputStream, int);
   }
@@ -623,6 +628,7 @@
     method public void resetCarrierFrequencyHz();
     method public deprecated void resetCarrierPhase();
     method public deprecated void resetCarrierPhaseUncertainty();
+    method public void resetCodeType();
     method public void resetSnrInDb();
     method public void set(android.location.GnssMeasurement);
     method public void setAccumulatedDeltaRangeMeters(double);
@@ -634,6 +640,7 @@
     method public deprecated void setCarrierPhase(double);
     method public deprecated void setCarrierPhaseUncertainty(double);
     method public void setCn0DbHz(double);
+    method public void setCodeType(int);
     method public void setConstellationType(int);
     method public void setMultipathIndicator(int);
     method public void setPseudorangeRateMetersPerSecond(double);
@@ -790,6 +797,134 @@
     method public static java.io.File getStorageDirectory();
   }
 
+  public abstract class HwBinder implements android.os.IHwBinder {
+    ctor public HwBinder();
+    method public static final void configureRpcThreadpool(long, boolean);
+    method public static void enableInstrumentation();
+    method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String) throws java.util.NoSuchElementException, android.os.RemoteException;
+    method public static final android.os.IHwBinder getService(java.lang.String, java.lang.String, boolean) throws java.util.NoSuchElementException, android.os.RemoteException;
+    method public static final void joinRpcThreadpool();
+    method public abstract void onTransact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
+    method public final void registerService(java.lang.String) throws android.os.RemoteException;
+    method public final void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
+  }
+
+  public class HwBlob {
+    ctor public HwBlob(int);
+    method public final void copyToBoolArray(long, boolean[], int);
+    method public final void copyToDoubleArray(long, double[], int);
+    method public final void copyToFloatArray(long, float[], int);
+    method public final void copyToInt16Array(long, short[], int);
+    method public final void copyToInt32Array(long, int[], int);
+    method public final void copyToInt64Array(long, long[], int);
+    method public final void copyToInt8Array(long, byte[], int);
+    method public final boolean getBool(long);
+    method public final double getDouble(long);
+    method public final float getFloat(long);
+    method public final short getInt16(long);
+    method public final int getInt32(long);
+    method public final long getInt64(long);
+    method public final byte getInt8(long);
+    method public final java.lang.String getString(long);
+    method public final long handle();
+    method public final void putBlob(long, android.os.HwBlob);
+    method public final void putBool(long, boolean);
+    method public final void putBoolArray(long, boolean[]);
+    method public final void putDouble(long, double);
+    method public final void putDoubleArray(long, double[]);
+    method public final void putFloat(long, float);
+    method public final void putFloatArray(long, float[]);
+    method public final void putInt16(long, short);
+    method public final void putInt16Array(long, short[]);
+    method public final void putInt32(long, int);
+    method public final void putInt32Array(long, int[]);
+    method public final void putInt64(long, long);
+    method public final void putInt64Array(long, long[]);
+    method public final void putInt8(long, byte);
+    method public final void putInt8Array(long, byte[]);
+    method public final void putNativeHandle(long, android.os.NativeHandle);
+    method public final void putString(long, java.lang.String);
+    method public static java.lang.Boolean[] wrapArray(boolean[]);
+    method public static java.lang.Long[] wrapArray(long[]);
+    method public static java.lang.Byte[] wrapArray(byte[]);
+    method public static java.lang.Short[] wrapArray(short[]);
+    method public static java.lang.Integer[] wrapArray(int[]);
+    method public static java.lang.Float[] wrapArray(float[]);
+    method public static java.lang.Double[] wrapArray(double[]);
+  }
+
+  public class HwParcel {
+    ctor public HwParcel();
+    method public final void enforceInterface(java.lang.String);
+    method public final boolean readBool();
+    method public final java.util.ArrayList<java.lang.Boolean> readBoolVector();
+    method public final android.os.HwBlob readBuffer(long);
+    method public final double readDouble();
+    method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
+    method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
+    method public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
+    method public final float readFloat();
+    method public final java.util.ArrayList<java.lang.Float> readFloatVector();
+    method public final short readInt16();
+    method public final java.util.ArrayList<java.lang.Short> readInt16Vector();
+    method public final int readInt32();
+    method public final java.util.ArrayList<java.lang.Integer> readInt32Vector();
+    method public final long readInt64();
+    method public final java.util.ArrayList<java.lang.Long> readInt64Vector();
+    method public final byte readInt8();
+    method public final java.util.ArrayList<java.lang.Byte> readInt8Vector();
+    method public final android.os.NativeHandle readNativeHandle();
+    method public final java.util.ArrayList<android.os.NativeHandle> readNativeHandleVector();
+    method public final java.lang.String readString();
+    method public final java.util.ArrayList<java.lang.String> readStringVector();
+    method public final android.os.IHwBinder readStrongBinder();
+    method public final void release();
+    method public final void releaseTemporaryStorage();
+    method public final void send();
+    method public final void verifySuccess();
+    method public final void writeBool(boolean);
+    method public final void writeBoolVector(java.util.ArrayList<java.lang.Boolean>);
+    method public final void writeBuffer(android.os.HwBlob);
+    method public final void writeDouble(double);
+    method public final void writeDoubleVector(java.util.ArrayList<java.lang.Double>);
+    method public final void writeFloat(float);
+    method public final void writeFloatVector(java.util.ArrayList<java.lang.Float>);
+    method public final void writeInt16(short);
+    method public final void writeInt16Vector(java.util.ArrayList<java.lang.Short>);
+    method public final void writeInt32(int);
+    method public final void writeInt32Vector(java.util.ArrayList<java.lang.Integer>);
+    method public final void writeInt64(long);
+    method public final void writeInt64Vector(java.util.ArrayList<java.lang.Long>);
+    method public final void writeInt8(byte);
+    method public final void writeInt8Vector(java.util.ArrayList<java.lang.Byte>);
+    method public final void writeInterfaceToken(java.lang.String);
+    method public final void writeNativeHandle(android.os.NativeHandle);
+    method public final void writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>);
+    method public final void writeStatus(int);
+    method public final void writeString(java.lang.String);
+    method public final void writeStringVector(java.util.ArrayList<java.lang.String>);
+    method public final void writeStrongBinder(android.os.IHwBinder);
+    field public static final int STATUS_SUCCESS = 0; // 0x0
+  }
+
+  public static abstract class HwParcel.Status implements java.lang.annotation.Annotation {
+  }
+
+  public abstract interface IHwBinder {
+    method public abstract boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
+    method public abstract android.os.IHwInterface queryLocalInterface(java.lang.String);
+    method public abstract void transact(int, android.os.HwParcel, android.os.HwParcel, int) throws android.os.RemoteException;
+    method public abstract boolean unlinkToDeath(android.os.IHwBinder.DeathRecipient);
+  }
+
+  public static abstract interface IHwBinder.DeathRecipient {
+    method public abstract void serviceDied(long);
+  }
+
+  public abstract interface IHwInterface {
+    method public abstract android.os.IHwBinder asBinder();
+  }
+
   public class IncidentManager {
     method public void reportIncident(android.os.IncidentReportArgs);
   }
@@ -810,6 +945,18 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
+  public final class NativeHandle implements java.io.Closeable {
+    ctor public NativeHandle();
+    ctor public NativeHandle(java.io.FileDescriptor, boolean);
+    ctor public NativeHandle(java.io.FileDescriptor[], int[], boolean);
+    method public void close() throws java.io.IOException;
+    method public android.os.NativeHandle dup() throws java.io.IOException;
+    method public java.io.FileDescriptor getFileDescriptor();
+    method public java.io.FileDescriptor[] getFileDescriptors();
+    method public int[] getInts();
+    method public boolean hasSingleFileDescriptor();
+  }
+
   public final class MessageQueue {
     method public int postSyncBarrier();
     method public void removeSyncBarrier(int);
@@ -825,6 +972,11 @@
 
   public class Process {
     method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
+    field public static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; // 0x15f90
+    field public static final int FIRST_ISOLATED_UID = 99000; // 0x182b8
+    field public static final int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; // 0x182b7
+    field public static final int LAST_ISOLATED_UID = 99999; // 0x1869f
+    field public static final int NUM_UIDS_PER_APP_ZYGOTE = 100; // 0x64
   }
 
   public final class RemoteCallback implements android.os.Parcelable {
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 8fa2980..3d74f8b 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -81,8 +81,7 @@
         case ui::Dataspace::V0_SRGB:
             return SkColorSpace::MakeSRGB();
         case ui::Dataspace::DISPLAY_P3:
-            return SkColorSpace::MakeRGB(
-                    SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
         default:
             return nullptr;
     }
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 9d37cdb..ad5eae3 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -57,7 +57,7 @@
                 break;
             case Subscription::SubscriberInformationCase::kPerfettoDetails:
                 if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details(),
-                                                            rule_id, configKey)) {
+                                                            subscription.id(), rule_id, configKey)) {
                     ALOGW("Failed to generate perfetto traces.");
                 }
                 break;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 860e40d..0fa7cff 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -181,6 +181,7 @@
         DocsUISearchTypeReported docs_ui_search_type_reported = 120;
         DataStallEvent data_stall_event = 121;
         RescuePartyResetReported rescue_party_reset_reported = 122;
+        SignedConfigReported signed_config_reported = 123;
     }
 
     // Pulled events will start at field 10000.
@@ -3802,7 +3803,7 @@
     //bionic/libc/include/netdb.h
     //system/netd/resolv/include/netd_resolv/resolv.h
     enum ReturnCode {
-        EAI_NO_ERR = 0;
+        EAI_NO_ERROR = 0;
         EAI_ADDRFAMILY = 1;
         EAI_AGAIN = 2;
         EAI_BADFLAGS = 3;
@@ -3859,3 +3860,45 @@
     // The rescue level of this reset. A value of 0 indicates missing or unknown level information.
     optional int32 rescue_level = 1;
 }
+
+/**
+ * Logs when signed config is received from an APK, and if that config was applied successfully.
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/signedconfig/SignedConfigService.java
+ */
+message SignedConfigReported {
+    enum Type {
+        UNKNOWN_TYPE = 0;
+        GLOBAL_SETTINGS = 1;
+    }
+    optional Type type = 1;
+
+    // The final status of the signed config received.
+    enum Status {
+        UNKNOWN_STATUS = 0;
+        APPLIED = 1;
+        BASE64_FAILURE_CONFIG = 2;
+        BASE64_FAILURE_SIGNATURE = 3;
+        SECURITY_EXCEPTION = 4;
+        INVALID_CONFIG = 5;
+        OLD_CONFIG = 6;
+        SIGNATURE_CHECK_FAILED = 7;
+        NOT_APPLICABLE = 8;
+        SIGNATURE_CHECK_FAILED_PROD_KEY_ABSENT = 9;
+    }
+    optional Status status = 2;
+
+    // The version of the signed config processed.
+    optional int32 version = 3;
+
+    // The package name that the config was extracted from.
+    optional string from_package = 4;
+
+    enum Key {
+        NO_KEY = 0;
+        DEBUG = 1;
+        PRODUCTION = 2;
+    }
+    // Which key was used to verify the config.
+    optional Key verified_with = 5;
+}
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
index 42cc543..0c4c330 100644
--- a/cmds/statsd/src/external/Perfetto.cpp
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -39,6 +39,7 @@
 namespace statsd {
 
 bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config,
+                                            int64_t subscription_id,
                                             int64_t alert_id,
                                             const ConfigKey& configKey) {
     VLOG("Starting trace collection through perfetto");
@@ -48,9 +49,11 @@
         return false;
     }
 
-    char alertId[20];
-    char configId[20];
-    char configUid[20];
+    char subscriptionId[25];
+    char alertId[25];
+    char configId[25];
+    char configUid[25];
+    snprintf(subscriptionId, sizeof(subscriptionId), "%" PRId64, subscription_id);
     snprintf(alertId, sizeof(alertId), "%" PRId64, alert_id);
     snprintf(configId, sizeof(configId), "%" PRId64, configKey.GetId());
     snprintf(configUid, sizeof(configUid), "%d", configKey.GetUid());
@@ -94,7 +97,7 @@
 
         execl("/system/bin/perfetto", "perfetto", "--background", "--config", "-", "--dropbox",
               kDropboxTag, "--alert-id", alertId, "--config-id", configId, "--config-uid",
-              configUid, nullptr);
+              configUid, "--subscription-id", subscriptionId, nullptr);
 
         // execl() doesn't return in case of success, if we get here something
         // failed.
diff --git a/cmds/statsd/src/external/Perfetto.h b/cmds/statsd/src/external/Perfetto.h
index 1e7f728..ab2c195 100644
--- a/cmds/statsd/src/external/Perfetto.h
+++ b/cmds/statsd/src/external/Perfetto.h
@@ -32,6 +32,7 @@
 // This method returns immediately after passing the config and does NOT wait
 // for the full duration of the trace.
 bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config,
+                                            int64_t subscription_id,
                                             int64_t alert_id,
                                             const ConfigKey& configKey);
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c90e404..1f01e26 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -317,4 +317,7 @@
 
     /** Returns true if the given uid is the app in the foreground. */
     public abstract boolean isAppForeground(int uid);
+
+    /** Remove pending backup for the given userId. */
+    public abstract void clearPendingBackup(int userId);
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 94983e1..9bcb36f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2276,6 +2276,16 @@
     }
 
     @Override
+    public String[] setDistractingPackageRestrictions(String[] packages, int distractionFlags) {
+        try {
+            return mPM.setDistractingPackageRestrictionsAsUser(packages, distractionFlags,
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
             PersistableBundle appExtras, PersistableBundle launcherExtras,
             String dialogMessage) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 347973e..fb65da1 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -317,7 +317,6 @@
      */
     void requestWifiBugReport(in String shareTitle, in String shareDescription);
 
-    void clearPendingBackup();
     Intent getIntentForIntentSender(in IIntentSender sender);
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 27581fc..a6abe0b 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -179,16 +179,6 @@
     public static final String ACTION_REQUEST_ROLE = "android.app.role.action.REQUEST_ROLE";
 
     /**
-     * The name of the requested role.
-     * <p>
-     * <strong>Type:</strong> String
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME";
-
-    /**
      * The permission required to manage records of role holders in {@link RoleManager} directly.
      *
      * @hide
@@ -236,7 +226,7 @@
         Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
         Intent intent = new Intent(ACTION_REQUEST_ROLE);
         intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
-        intent.putExtra(EXTRA_REQUEST_ROLE_NAME, roleName);
+        intent.putExtra(Intent.EXTRA_ROLE_NAME, roleName);
         return intent;
     }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e37126b..d27cce5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1833,6 +1833,37 @@
             "android.intent.action.REVIEW_PERMISSIONS";
 
     /**
+     * Activity action: Launch UI to manage a default app.
+     * <p>
+     * Input: {@link #EXTRA_ROLE_NAME} specifies the role of the default app which will be managed
+     * by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS)
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @SystemApi
+    public static final String ACTION_MANAGE_DEFAULT_APP =
+            "android.intent.action.MANAGE_DEFAULT_APP";
+
+    /**
+     * Intent extra: A role name.
+     * <p>
+     * Type: String
+     * </p>
+     *
+     * @see android.app.role.RoleManager
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_ROLE_NAME = "android.intent.extra.ROLE_NAME";
+
+    /**
      * Activity action: Launch UI to manage special app accesses.
      * <p>
      * Input: Nothing.
@@ -2411,6 +2442,25 @@
     public static final String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
 
     /**
+     * Broadcast Action: Distracting packages have been changed.
+     * <p>Includes the following extras:
+     * <ul>
+     * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been changed.
+     * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been changed.
+     * <li> {@link #EXTRA_DISTRACTION_RESTRICTIONS} the new restrictions set on these packages.
+     * </ul>
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system. It is only sent to registered receivers.
+     *
+     * @see PackageManager#setDistractingPackageRestrictions(String[], int)
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_DISTRACTING_PACKAGES_CHANGED =
+            "android.intent.action.DISTRACTING_PACKAGES_CHANGED";
+
+    /**
      * Broadcast Action: Sent to a package that has been suspended by the system. This is sent
      * whenever a package is put into a suspended state or any of its app extras change while in the
      * suspended state.
@@ -5120,6 +5170,17 @@
             "android.intent.extra.changed_uid_list";
 
     /**
+     * An integer denoting a bitwise combination of restrictions set on distracting packages via
+     * {@link PackageManager#setDistractingPackageRestrictions(String[], int)}
+     *
+     * @hide
+     * @see PackageManager.DistractionRestriction
+     * @see PackageManager#setDistractingPackageRestrictions(String[], int)
+     */
+    public static final String EXTRA_DISTRACTION_RESTRICTIONS =
+            "android.intent.extra.distraction_restrictions";
+
+    /**
      * @hide
      * Magic extra system code can use when binding, to give a label for
      * who it is that has bound to a service.  This is an integer giving
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index ba7710b..db2b6fd 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -69,6 +69,7 @@
             int userId);
 
     boolean hasShortcutHostPermission(String callingPackage);
+    boolean shouldHideFromSuggestions(String packageName, in UserHandle user);
 
     ParceledListSlice getShortcutConfigActivities(
             String callingPackage, String packageName, in UserHandle user);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 64a4479b..d5c3b26 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -273,6 +273,9 @@
 
     void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage);
 
+    String[] setDistractingPackageRestrictionsAsUser(in String[] packageNames, int restrictionFlags,
+            int userId);
+
     String[] setPackagesSuspendedAsUser(in String[] packageNames, boolean suspended,
             in PersistableBundle appExtras, in PersistableBundle launcherExtras,
             in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 44e652f..983ea9f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -697,6 +697,26 @@
     }
 
     /**
+     * Returns whether a package should be hidden from suggestions to the user. Currently, this
+     * could be done because the package was marked as distracting to the user via
+     * {@code PackageManager.setDistractingPackageRestrictions(String[], int)}.
+     *
+     * @param packageName The package for which to check.
+     * @param user the {@link UserHandle} of the profile.
+     * @return
+     */
+    public boolean shouldHideFromSuggestions(@NonNull String packageName,
+            @NonNull UserHandle user) {
+        Preconditions.checkNotNull(packageName, "packageName");
+        Preconditions.checkNotNull(user, "user");
+        try {
+            return mService.shouldHideFromSuggestions(packageName, user);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
      *
      * @param packageName The package name of the application
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2aeb68d..636a70f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5889,6 +5889,74 @@
     public abstract boolean isSignedByExactly(String packageName, KeySet ks);
 
     /**
+     * Flag to denote no restrictions. This should be used to clear any restrictions that may have
+     * been previously set for the package.
+     * @see PackageManager.DistractionRestriction
+     * @hide
+     */
+    @SystemApi
+    public static final int RESTRICTION_NONE = 0x0;
+
+    /**
+     * Flag to denote that a package should be hidden from any suggestions to the user.
+     * @see PackageManager.DistractionRestriction
+     * @hide
+     */
+    @SystemApi
+    public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 0x00000001;
+
+    /**
+     * Flag to denote that a package's notifications should be hidden.
+     * @see PackageManager.DistractionRestriction
+     * @hide
+     */
+    @SystemApi
+    public static final int RESTRICTION_HIDE_NOTIFICATIONS = 0x00000002;
+
+    /**
+     * Restriction flags to set on a package that is considered as distracting to the user.
+     * These should help the user to restrict their usage of these apps.
+     *
+     * @see #setDistractingPackageRestrictions(String[], int)
+     * @hide
+     */
+    @SystemApi
+    @IntDef(flag = true, prefix = {"RESTRICTION_"}, value = {
+            RESTRICTION_NONE,
+            RESTRICTION_HIDE_FROM_SUGGESTIONS,
+            RESTRICTION_HIDE_NOTIFICATIONS
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DistractionRestriction {}
+
+    /**
+     * Mark or unmark the given packages as distracting to the user.
+     * These packages can have certain restrictions set that should discourage the user to launch
+     * them often. For example, notifications from such an app can be hidden, or the app can be
+     * removed from launcher suggestions, so the user is able to restrict their use of these apps.
+     *
+     * <p>The caller must hold {@link android.Manifest.permission#SUSPEND_APPS} to use this API.
+     *
+     * @param packages Packages to mark as distracting.
+     * @param restrictionFlags Any combination of {@link DistractionRestriction restrictions} to
+     *                         impose on the given packages. {@link #RESTRICTION_NONE} can be used
+     *                         to clear any existing restrictions.
+     * @return A list of packages that could not have the {@code restrictionFlags} set. The system
+     * may prevent restricting critical packages to preserve normal device function.
+     *
+     * @see DistractionRestriction
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.SUSPEND_APPS)
+    @NonNull
+    public String[] setDistractingPackageRestrictions(@NonNull String[] packages,
+            @DistractionRestriction int restrictionFlags) {
+        throw new UnsupportedOperationException(
+                "setDistractingPackageRestrictions not implemented");
+    }
+
+    /**
      * Puts the package in a suspended state, where attempts at starting activities are denied.
      *
      * <p>It doesn't remove the data or the actual package file. The application's notifications
@@ -5911,8 +5979,7 @@
      * {@link PersistableBundle} objects to be shared with the apps being suspended and the
      * launcher to support customization that they might need to handle the suspended state.
      *
-     * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} or
-     * {@link Manifest.permission#MANAGE_USERS} to use this api.</p>
+     * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} to use this API.
      *
      * @param packageNames The names of the packages to set the suspended status.
      * @param suspended If set to {@code true}, the packages will be suspended, if set to
@@ -5955,7 +6022,7 @@
      * <p>When the user tries to launch a suspended app, a system dialog alerting them that the app
      * is suspended will be shown instead.
      * The caller can optionally customize the dialog by passing a {@link SuspendDialogInfo} object
-     * to this api. This dialog will have a button that starts the
+     * to this API. This dialog will have a button that starts the
      * {@link Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} intent if the suspending app declares an
      * activity which handles this action.
      *
@@ -5966,7 +6033,7 @@
      * {@link PersistableBundle} objects to be shared with the apps being suspended and the
      * launcher to support customization that they might need to handle the suspended state.
      *
-     * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} to use this api.
+     * <p>The caller must hold {@link Manifest.permission#SUSPEND_APPS} to use this API.
      *
      * @param packageNames The names of the packages to set the suspended status.
      * @param suspended If set to {@code true}, the packages will be suspended, if set to
@@ -6005,7 +6072,7 @@
      * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
      * SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical
      * packages to keep the device in a functioning state, e.g. the default dialer.
-     * Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this api.
+     * Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this API.
      *
      * <p>
      * Note that this set of critical packages can change with time, so even though a package name
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 83979e9..83563d0 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -284,6 +284,17 @@
     public abstract SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId);
 
     /**
+     * Gets any distraction flags set via
+     * {@link PackageManager#setDistractingPackageRestrictions(String[], int)}
+     *
+     * @param packageName
+     * @param userId
+     * @return A bitwise OR of any of the {@link PackageManager.DistractionRestriction}
+     */
+    public abstract @PackageManager.DistractionRestriction int getDistractingPackageRestrictions(
+            String packageName, int userId);
+
+    /**
      * Do a straight uid lookup for the given package/application in the given user.
      * @see PackageManager#getPackageUidAsUser(String, int, int)
      * @return The app's uid, or < 0 if the package was not found in that user
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 74dd08f..249b691 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -54,6 +54,7 @@
     public boolean stopped;
     public boolean notLaunched;
     public boolean hidden; // Is the app restricted by owner / admin
+    public int distractionFlags;
     public boolean suspended;
     public String suspendingPackage;
     public SuspendDialogInfo dialogInfo;
@@ -92,6 +93,7 @@
         stopped = o.stopped;
         notLaunched = o.notLaunched;
         hidden = o.hidden;
+        distractionFlags = o.distractionFlags;
         suspended = o.suspended;
         suspendingPackage = o.suspendingPackage;
         dialogInfo = o.dialogInfo;
@@ -222,6 +224,9 @@
         if (hidden != oldState.hidden) {
             return false;
         }
+        if (distractionFlags != oldState.distractionFlags) {
+            return false;
+        }
         if (suspended != oldState.suspended) {
             return false;
         }
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index bb8c92d..a3395ac 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -158,6 +158,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static final int PROTECTION_FLAG_OEM = 0x4000;
 
     /**
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index f1a4db2..9e0a9ba 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -732,6 +732,38 @@
         }
     }
 
+    /**
+     * Enable resource resolution logging to track the steps taken to resolve the last resource
+     * entry retrieved. Stores the configuration and package names for each step.
+     *
+     * Default disabled.
+     *
+     * @param enabled Boolean indicating whether to enable or disable logging.
+     *
+     * @hide
+     */
+    public void setResourceResolutionLoggingEnabled(boolean enabled) {
+        synchronized (this) {
+            ensureValidLocked();
+            nativeSetResourceResolutionLoggingEnabled(mObject, enabled);
+        }
+    }
+
+    /**
+     * Retrieve the last resource resolution path logged.
+     *
+     * @return Formatted string containing last resource ID/name and steps taken to resolve final
+     * entry, including configuration and package names.
+     *
+     * @hide
+     */
+    public @Nullable String getLastResourceResolution() {
+        synchronized (this) {
+            ensureValidLocked();
+            return nativeGetLastResourceResolution(mObject);
+        }
+    }
+
     CharSequence getPooledStringForCookie(int cookie, int id) {
         // Cookies map to ApkAssets starting at 1.
         return getApkAssets()[cookie - 1].getStringFromPool(id);
@@ -1383,6 +1415,8 @@
     private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid);
     private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem);
     private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr);
+    private static native void nativeSetResourceResolutionLoggingEnabled(long ptr, boolean enabled);
+    private static native @Nullable String nativeGetLastResourceResolution(long ptr);
 
     // Style attribute retrieval native methods.
     private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 365ceac..c4b315e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -2010,22 +2010,36 @@
     public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
         return mResourcesImpl.getResourceTypeName(resid);
     }
-    
+
     /**
      * Return the entry name for a given resource identifier.
-     * 
+     *
      * @param resid The resource identifier whose entry name is to be
      * retrieved.
-     * 
+     *
      * @return A string holding the entry name of the resource.
-     * 
+     *
      * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
-     * 
+     *
      * @see #getResourceName
      */
     public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
         return mResourcesImpl.getResourceEntryName(resid);
     }
+
+    /**
+     * Return formatted log of the last retrieved resource's resolution path.
+     *
+     * @return A string holding a formatted log of the steps taken to resolve the last resource.
+     *
+     * @throws NotFoundException Throws NotFoundException if there hasn't been a resource
+     * resolved yet.
+     *
+     * @hide
+     */
+    public String getLastResourceResolution() throws NotFoundException {
+        return mResourcesImpl.getLastResourceResolution();
+    }
     
     /**
      * Parse a series of {@link android.R.styleable#Extra &lt;extra&gt;} tags from
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 2ad4f62..77796d9 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -299,6 +299,13 @@
     }
 
     @NonNull
+    String getLastResourceResolution() throws NotFoundException {
+        String str = mAssets.getLastResourceResolution();
+        if (str != null) return str;
+        throw new NotFoundException("Associated AssetManager hasn't resolved a resource");
+    }
+
+    @NonNull
     CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
         PluralRules rule = getPluralRule();
         CharSequence res = mAssets.getResourceBagText(id,
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 4a466f3..617125b3 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -66,6 +66,7 @@
     private int mMtu;
     // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
     private String mTcpBufferSizes;
+    private IpPrefix mNat64Prefix;
 
     private static final int MIN_MTU    = 68;
     private static final int MIN_MTU_V6 = 1280;
@@ -760,6 +761,32 @@
     }
 
     /**
+     * Returns the NAT64 prefix in use on this link, if any.
+     *
+     * @return the NAT64 prefix.
+     * @hide
+     */
+    public @Nullable IpPrefix getNat64Prefix() {
+        return mNat64Prefix;
+    }
+
+    /**
+     * Sets the NAT64 prefix in use on this link.
+     *
+     * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the
+     * 128-bit IPv6 address) are supported.
+     *
+     * @param prefix the NAT64 prefix.
+     * @hide
+     */
+    public void setNat64Prefix(IpPrefix prefix) {
+        if (prefix != null && prefix.getPrefixLength() != 96) {
+            throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix);
+        }
+        mNat64Prefix = prefix;  // IpPrefix objects are immutable.
+    }
+
+    /**
      * Adds a stacked link.
      *
      * If there is already a stacked link with the same interface name as link,
@@ -831,6 +858,7 @@
         mStackedLinks.clear();
         mMtu = 0;
         mTcpBufferSizes = null;
+        mNat64Prefix = null;
     }
 
     /**
@@ -908,6 +936,11 @@
             resultJoiner.add(mHttpProxy.toString());
         }
 
+        if (mNat64Prefix != null) {
+            resultJoiner.add("Nat64Prefix:");
+            resultJoiner.add(mNat64Prefix.toString());
+        }
+
         final Collection<LinkProperties> stackedLinksValues = mStackedLinks.values();
         if (!stackedLinksValues.isEmpty()) {
             final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]");
@@ -1295,6 +1328,17 @@
     }
 
     /**
+     * Compares this {@code LinkProperties} NAT64 prefix against the target.
+     *
+     * @param target LinkProperties to compare.
+     * @return {@code true} if both are identical, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isIdenticalNat64Prefix(LinkProperties target) {
+        return Objects.equals(mNat64Prefix, target.mNat64Prefix);
+    }
+
+    /**
      * Compares this {@code LinkProperties} instance against the target
      * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
      * all their fields are equal in values.
@@ -1330,7 +1374,8 @@
                 && isIdenticalHttpProxy(target)
                 && isIdenticalStackedLinks(target)
                 && isIdenticalMtu(target)
-                && isIdenticalTcpBufferSizes(target);
+                && isIdenticalTcpBufferSizes(target)
+                && isIdenticalNat64Prefix(target);
     }
 
     /**
@@ -1443,7 +1488,8 @@
                 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
                 + (mUsePrivateDns ? 57 : 0)
                 + mPcscfs.size() * 67
-                + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode());
+                + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
+                + Objects.hash(mNat64Prefix);
     }
 
     /**
@@ -1484,6 +1530,8 @@
         } else {
             dest.writeByte((byte)0);
         }
+        dest.writeParcelable(mNat64Prefix, 0);
+
         ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
         dest.writeList(stackedLinks);
     }
@@ -1535,6 +1583,7 @@
                 if (in.readByte() == 1) {
                     netProp.setHttpProxy(in.readParcelable(null));
                 }
+                netProp.setNat64Prefix(in.readParcelable(null));
                 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
                 in.readList(stackedLinks, LinkProperties.class.getClassLoader());
                 for (LinkProperties stackedLink: stackedLinks) {
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 1343d24..b15a4d3 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -114,7 +114,6 @@
         }
     }
 
-
     // TODO(b/111441001) Connect up with BugreportListener methods.
     private final class DumpstateListener extends IDumpstateListener.Stub
             implements DeathRecipient {
@@ -130,6 +129,23 @@
         }
 
         @Override
+        public void onProgress(int progress) throws RemoteException {
+            // TODO(b/111441001): implement
+        }
+
+        @Override
+        public void onError(int errorCode) throws RemoteException {
+            // TODO(b/111441001): implement
+        }
+
+        @Override
+        public void onFinished(long durationMs, String title, String description)
+                throws RemoteException {
+            // TODO(b/111441001): implement
+        }
+
+        // Old methods; should go away
+        @Override
         public void onProgressUpdated(int progress) throws RemoteException {
             // TODO(b/111441001): implement
         }
diff --git a/core/java/android/os/HwBinder.java b/core/java/android/os/HwBinder.java
index 3de3494..9e3e83e 100644
--- a/core/java/android/os/HwBinder.java
+++ b/core/java/android/os/HwBinder.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -24,6 +25,7 @@
 
 /** @hide */
 @SystemApi
+@TestApi
 public abstract class HwBinder implements IHwBinder {
     private static final String TAG = "HwBinder";
 
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
index 6a5bb1c..0ec63b5 100644
--- a/core/java/android/os/HwBlob.java
+++ b/core/java/android/os/HwBlob.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -28,6 +29,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public class HwBlob {
     private static final String TAG = "HwBlob";
 
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 7a51db2..7919a00 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 import libcore.util.NativeAllocationRegistry;
 
@@ -28,6 +29,7 @@
 
 /** @hide */
 @SystemApi
+@TestApi
 public class HwParcel {
     private static final String TAG = "HwParcel";
 
diff --git a/core/java/android/os/IHwBinder.java b/core/java/android/os/IHwBinder.java
index 249eb3a..46fa6ef 100644
--- a/core/java/android/os/IHwBinder.java
+++ b/core/java/android/os/IHwBinder.java
@@ -17,9 +17,11 @@
 package android.os;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 /** @hide */
 @SystemApi
+@TestApi
 public interface IHwBinder {
     /**
      * Process a hwbinder transaction.
diff --git a/core/java/android/os/IHwInterface.java b/core/java/android/os/IHwInterface.java
index f9edd5b..0a5a715 100644
--- a/core/java/android/os/IHwInterface.java
+++ b/core/java/android/os/IHwInterface.java
@@ -17,8 +17,11 @@
 package android.os;
 
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
+
 /** @hide */
 @SystemApi
+@TestApi
 public interface IHwInterface {
     /**
      * @return the binder object that corresponds to this interface.
diff --git a/core/java/android/os/NativeHandle.java b/core/java/android/os/NativeHandle.java
index f7ffc37..f13bf5f 100644
--- a/core/java/android/os/NativeHandle.java
+++ b/core/java/android/os/NativeHandle.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.system.ErrnoException;
 import android.system.Os;
 
@@ -32,6 +33,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class NativeHandle implements Closeable {
     // whether this object owns mFds
     private boolean mOwn = false;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ee56e3d..760fef7 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -208,30 +208,35 @@
      * First uid used for fully isolated sandboxed processes spawned from an app zygote
      * @hide
      */
+    @TestApi
     public static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
 
     /**
      * Number of UIDs we allocate per application zygote
      * @hide
      */
+    @TestApi
     public static final int NUM_UIDS_PER_APP_ZYGOTE = 100;
 
     /**
      * Last uid used for fully isolated sandboxed processes spawned from an app zygote
      * @hide
      */
+    @TestApi
     public static final int LAST_APP_ZYGOTE_ISOLATED_UID = 98999;
 
     /**
      * First uid used for fully isolated sandboxed processes (with no permissions of their own)
      * @hide
      */
+    @TestApi
     public static final int FIRST_ISOLATED_UID = 99000;
 
     /**
      * Last uid used for fully isolated sandboxed processes (with no permissions of their own)
      * @hide
      */
+    @TestApi
     public static final int LAST_ISOLATED_UID = 99999;
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ef117ea..64aa062 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8681,10 +8681,10 @@
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_CHANGER);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
-            CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
             if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
                 CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
                 CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
+                CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
                 CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER);
                 CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE);
             }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index eef7ea2..50e7ec3 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -37,7 +37,6 @@
 import com.android.i18n.phonenumbers.PhoneNumberMatch;
 import com.android.i18n.phonenumbers.PhoneNumberUtil;
 import com.android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
-import com.android.internal.annotations.GuardedBy;
 
 import libcore.util.EmptyArray;
 
@@ -49,6 +48,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Locale;
+import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -69,7 +69,6 @@
  *
  * @see MatchFilter
  * @see TransformFilter
- * @see UrlSpanFactory
  */
 
 public class Linkify {
@@ -228,44 +227,6 @@
     }
 
     /**
-     * Factory class to create {@link URLSpan}s. While adding spans to a {@link Spannable},
-     * {@link Linkify} will call {@link UrlSpanFactory#create(String)} function to create a
-     * {@link URLSpan}.
-     *
-     * @see #addLinks(Spannable, int, UrlSpanFactory)
-     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
-     * UrlSpanFactory)
-     */
-    public static class UrlSpanFactory {
-        private static final Object sInstanceLock = new Object();
-
-        @GuardedBy("sInstanceLock")
-        private static volatile UrlSpanFactory sInstance = null;
-
-        private static synchronized UrlSpanFactory getInstance() {
-            if (sInstance == null) {
-                synchronized (sInstanceLock) {
-                    if (sInstance == null) {
-                        sInstance = new UrlSpanFactory();
-                    }
-                }
-            }
-            return sInstance;
-        }
-
-        /**
-         * Factory function that will called by {@link Linkify} in order to create a
-         * {@link URLSpan}.
-         *
-         * @param url URL found
-         * @return a URLSpan instance
-         */
-        public URLSpan create(final String url) {
-            return new URLSpan(url);
-        }
-    }
-
-    /**
      *  Scans the text of the provided Spannable and turns all occurrences
      *  of the link types indicated in the mask into clickable links.
      *  If the mask is nonzero, it also removes any existing URLSpans
@@ -277,7 +238,7 @@
      *
      *  @return True if at least one link is found and applied.
      *
-     * @see #addLinks(Spannable, int, UrlSpanFactory)
+     * @see #addLinks(Spannable, int, Function)
      */
     public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
         return addLinks(text, mask, null, null);
@@ -292,11 +253,11 @@
      *
      *  @param text Spannable whose text is to be marked-up with links
      *  @param mask mask to define which kinds of links will be searched
-     *  @param urlSpanFactory factory class used to create {@link URLSpan}s
+     *  @param urlSpanFactory function used to create {@link URLSpan}s
      *  @return True if at least one link is found and applied.
      */
     public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
-            @Nullable UrlSpanFactory urlSpanFactory) {
+            @Nullable Function<String, URLSpan> urlSpanFactory) {
         return addLinks(text, mask, null, urlSpanFactory);
     }
 
@@ -309,11 +270,11 @@
      * @param text Spannable whose text is to be marked-up with links
      * @param mask mask to define which kinds of links will be searched
      * @param context Context to be used while identifying phone numbers
-     * @param urlSpanFactory factory class used to create {@link URLSpan}s
+     * @param urlSpanFactory function used to create {@link URLSpan}s
      * @return true if at least one link is found and applied.
      */
     private static boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
-            @Nullable Context context, @Nullable UrlSpanFactory urlSpanFactory) {
+            @Nullable Context context, @Nullable Function<String, URLSpan> urlSpanFactory) {
         if (text != null && containsUnsupportedCharacters(text.toString())) {
             android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
             return false;
@@ -398,7 +359,7 @@
      *
      *  @return True if at least one link is found and applied.
      *
-     *  @see #addLinks(Spannable, int, UrlSpanFactory)
+     *  @see #addLinks(Spannable, int, Function)
      */
     public static final boolean addLinks(@NonNull TextView text, @LinkifyMask int mask) {
         if (mask == 0) {
@@ -512,8 +473,7 @@
      *  @param pattern      Regex pattern to be used for finding links
      *  @param scheme       URL scheme string (eg <code>http://</code>) to be
      *                      prepended to the links that do not start with this scheme.
-     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
-     * UrlSpanFactory)
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter, Function)
      */
     public static final boolean addLinks(@NonNull Spannable text, @NonNull Pattern pattern,
             @Nullable String scheme) {
@@ -534,8 +494,7 @@
      * @param transformFilter Filter to allow the client code to update the link found.
      *
      * @return True if at least one link is found and applied.
-     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
-     * UrlSpanFactory)
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter, Function)
      */
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable String scheme, @Nullable MatchFilter matchFilter,
@@ -560,8 +519,7 @@
      *
      * @return True if at least one link is found and applied.
      *
-     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter,
-     * UrlSpanFactory)
+     * @see #addLinks(Spannable, Pattern, String, String[], MatchFilter, TransformFilter, Function)
      */
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable String defaultScheme, @Nullable String[] schemes,
@@ -584,14 +542,14 @@
      * @param matchFilter     the filter that is used to allow the client code additional control
      *                        over which pattern matches are to be converted into links.
      * @param transformFilter filter to allow the client code to update the link found.
-     * @param urlSpanFactory  factory class used to create {@link URLSpan}s
+     * @param urlSpanFactory  function used to create {@link URLSpan}s
      *
      * @return True if at least one link is found and applied.
      */
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable String defaultScheme, @Nullable String[] schemes,
             @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter,
-            @Nullable UrlSpanFactory urlSpanFactory) {
+            @Nullable Function<String, URLSpan> urlSpanFactory) {
         if (spannable != null && containsUnsupportedCharacters(spannable.toString())) {
             android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
             return false;
@@ -634,11 +592,11 @@
     }
 
     private static void applyLink(String url, int start, int end, Spannable text,
-            @Nullable UrlSpanFactory urlSpanFactory) {
+            @Nullable Function<String, URLSpan> urlSpanFactory) {
         if (urlSpanFactory == null) {
-            urlSpanFactory = UrlSpanFactory.getInstance();
+            urlSpanFactory = DEFAULT_SPAN_FACTORY;
         }
-        final URLSpan span = urlSpanFactory.create(url);
+        final URLSpan span = urlSpanFactory.apply(url);
         text.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
     }
 
@@ -805,6 +763,13 @@
             i++;
         }
     }
+
+    /**
+     * Default factory function to create {@link URLSpan}s. While adding spans to a
+     * {@link Spannable}, {@link Linkify} will call this function to create a {@link URLSpan}.
+     */
+    private static final Function<String, URLSpan> DEFAULT_SPAN_FACTORY =
+            (String string) -> new URLSpan(string);
 }
 
 class LinkSpec {
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java
new file mode 100644
index 0000000..1a6e5d8
--- /dev/null
+++ b/core/java/android/view/textclassifier/ConversationAction.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.textclassifier;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.app.RemoteAction;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+
+/** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
+public final class ConversationAction implements Parcelable {
+
+    /** @hide */
+    @Retention(SOURCE)
+    @StringDef(
+            value = {
+                    TYPE_VIEW_CALENDAR,
+                    TYPE_VIEW_MAP,
+                    TYPE_TRACK_FLIGHT,
+                    TYPE_OPEN_URL,
+                    TYPE_SEND_SMS,
+                    TYPE_CALL_PHONE,
+                    TYPE_SEND_EMAIL,
+                    TYPE_TEXT_REPLY,
+                    TYPE_CREATE_REMINDER,
+                    TYPE_SHARE_LOCATION
+            },
+            prefix = "TYPE_")
+    public @interface ActionType {}
+
+    /**
+     * Indicates an action to view a calendar at a specified time.
+     */
+    public static final String TYPE_VIEW_CALENDAR = "view_calendar";
+    /**
+     * Indicates an action to view the map at a specified location.
+     */
+    public static final String TYPE_VIEW_MAP = "view_map";
+    /**
+     * Indicates an action to track a flight.
+     */
+    public static final String TYPE_TRACK_FLIGHT = "track_flight";
+    /**
+     * Indicates an action to open an URL.
+     */
+    public static final String TYPE_OPEN_URL = "open_url";
+    /**
+     * Indicates an action to send a SMS.
+     */
+    public static final String TYPE_SEND_SMS = "send_sms";
+    /**
+     * Indicates an action to call a phone number.
+     */
+    public static final String TYPE_CALL_PHONE = "call_phone";
+    /**
+     * Indicates an action to send an email.
+     */
+    public static final String TYPE_SEND_EMAIL = "send_email";
+    /**
+     * Indicates an action to reply with a text message.
+     */
+    public static final String TYPE_TEXT_REPLY = "text_reply";
+    /**
+     * Indicates an action to create a reminder.
+     */
+    public static final String TYPE_CREATE_REMINDER = "create_reminder";
+    /**
+     * Indicates an action to reply with a location.
+     */
+    public static final String TYPE_SHARE_LOCATION = "share_location";
+
+    public static final Creator<ConversationAction> CREATOR =
+            new Creator<ConversationAction>() {
+                @Override
+                public ConversationAction createFromParcel(Parcel in) {
+                    return new ConversationAction(in);
+                }
+
+                @Override
+                public ConversationAction[] newArray(int size) {
+                    return new ConversationAction[size];
+                }
+            };
+
+    @NonNull
+    @ActionType
+    private final String mType;
+    @NonNull
+    private final CharSequence mTextReply;
+    @Nullable
+    private final RemoteAction mAction;
+
+    @FloatRange(from = 0, to = 1)
+    private final float mScore;
+
+    @NonNull
+    private final Bundle mExtras;
+
+    private ConversationAction(
+            @NonNull String type,
+            @Nullable RemoteAction action,
+            @Nullable CharSequence textReply,
+            float score,
+            @NonNull Bundle extras) {
+        mType = Preconditions.checkNotNull(type);
+        mAction = action;
+        mTextReply = textReply;
+        mScore = score;
+        mExtras = Preconditions.checkNotNull(extras);
+    }
+
+    private ConversationAction(Parcel in) {
+        mType = in.readString();
+        mAction = in.readParcelable(null);
+        mTextReply = in.readCharSequence();
+        mScore = in.readFloat();
+        mExtras = in.readBundle();
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mType);
+        parcel.writeParcelable(mAction, flags);
+        parcel.writeCharSequence(mTextReply);
+        parcel.writeFloat(mScore);
+        parcel.writeBundle(mExtras);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */
+    @NonNull
+    @ActionType
+    public String getType() {
+        return mType;
+    }
+
+    /**
+     * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for
+     * the specified action type.
+     */
+    @Nullable
+    public RemoteAction getAction() {
+        return mAction;
+    }
+
+    /**
+     * Returns the confidence score for the specified action. The value ranges from 0 (low
+     * confidence) to 1 (high confidence).
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getConfidenceScore() {
+        return mScore;
+    }
+
+    /**
+     * Returns the text reply that could be sent as a reply to the given conversation.
+     * <p>
+     * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}.
+     */
+    @Nullable
+    public CharSequence getTextReply() {
+        return mTextReply;
+    }
+
+    /**
+     * Returns the extended data related to this conversation action.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
+    /** Builder class to construct {@link ConversationAction}. */
+    public static final class Builder {
+        @Nullable
+        @ActionType
+        private String mType;
+        @Nullable
+        private RemoteAction mAction;
+        @Nullable
+        private CharSequence mTextReply;
+        private float mScore;
+        @Nullable
+        private Bundle mExtras;
+
+        public Builder(@NonNull @ActionType String actionType) {
+            mType = Preconditions.checkNotNull(actionType);
+        }
+
+        /**
+         * Sets an action that may be performed on the given conversation.
+         */
+        @NonNull
+        public Builder setAction(@Nullable RemoteAction action) {
+            mAction = action;
+            return this;
+        }
+
+        /**
+         * Sets a text reply that may be performed on the given conversation.
+         */
+        @NonNull
+        public Builder setTextReply(@Nullable CharSequence textReply) {
+            mTextReply = textReply;
+            return this;
+        }
+
+        /** Sets the confident score. */
+        @NonNull
+        public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) {
+            mScore = score;
+            return this;
+        }
+
+        /**
+         * Sets the extended data for the conversation action object.
+         */
+        @NonNull
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /** Builds the {@link ConversationAction} object. */
+        @NonNull
+        public ConversationAction build() {
+            return new ConversationAction(
+                    mType,
+                    mAction,
+                    mTextReply,
+                    mScore,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
+        }
+    }
+}
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index 3f690f7..f7c1a26 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -17,18 +17,15 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
-import android.annotation.FloatRange;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.app.Person;
-import android.app.RemoteAction;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.SpannedString;
-import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
@@ -37,10 +34,8 @@
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Represents a list of actions suggested by a {@link TextClassifier} on a given conversation.
@@ -62,83 +57,6 @@
                 }
             };
 
-    /** @hide */
-    @Retention(SOURCE)
-    @StringDef(
-            value = {
-                    TYPE_VIEW_CALENDAR,
-                    TYPE_VIEW_MAP,
-                    TYPE_TRACK_FLIGHT,
-                    TYPE_OPEN_URL,
-                    TYPE_SEND_SMS,
-                    TYPE_CALL_PHONE,
-                    TYPE_SEND_EMAIL,
-                    TYPE_TEXT_REPLY,
-                    TYPE_CREATE_REMINDER,
-                    TYPE_SHARE_LOCATION
-            },
-            prefix = "TYPE_")
-    public @interface ActionType {}
-
-    /**
-     * Indicates an action to view a calendar at a specified time.
-     */
-    public static final String TYPE_VIEW_CALENDAR = "view_calendar";
-    /**
-     * Indicates an action to view the map at a specified location.
-     */
-    public static final String TYPE_VIEW_MAP = "view_map";
-    /**
-     * Indicates an action to track a flight.
-     */
-    public static final String TYPE_TRACK_FLIGHT = "track_flight";
-    /**
-     * Indicates an action to open an URL.
-     */
-    public static final String TYPE_OPEN_URL = "open_url";
-    /**
-     * Indicates an action to send a SMS.
-     */
-    public static final String TYPE_SEND_SMS = "send_sms";
-    /**
-     * Indicates an action to call a phone number.
-     */
-    public static final String TYPE_CALL_PHONE = "call_phone";
-    /**
-     * Indicates an action to send an email.
-     */
-    public static final String TYPE_SEND_EMAIL = "send_email";
-    /**
-     * Indicates an action to reply with a text message.
-     */
-    public static final String TYPE_TEXT_REPLY = "text_reply";
-    /**
-     * Indicates an action to create a reminder.
-     */
-    public static final String TYPE_CREATE_REMINDER = "create_reminder";
-    /**
-     * Indicates an action to reply with a location.
-     */
-    public static final String TYPE_SHARE_LOCATION = "share_location";
-
-    /** @hide */
-    @Retention(SOURCE)
-    @StringDef(
-            value = {
-                    HINT_FOR_NOTIFICATION,
-                    HINT_FOR_IN_APP,
-            },
-            prefix = "HINT_")
-    public @interface Hint {}
-    /**
-     * To indicate the generated actions will be used within the app.
-     */
-    public static final String HINT_FOR_IN_APP = "in_app";
-    /**
-     * To indicate the generated actions will be used for notification.
-     */
-    public static final String HINT_FOR_NOTIFICATION = "notification";
-
     private final List<ConversationAction> mConversationActions;
     private final String mId;
 
@@ -184,182 +102,6 @@
         return mId;
     }
 
-    /** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
-    public static final class ConversationAction implements Parcelable {
-
-        public static final Creator<ConversationAction> CREATOR =
-                new Creator<ConversationAction>() {
-                    @Override
-                    public ConversationAction createFromParcel(Parcel in) {
-                        return new ConversationAction(in);
-                    }
-
-                    @Override
-                    public ConversationAction[] newArray(int size) {
-                        return new ConversationAction[size];
-                    }
-                };
-
-        @NonNull
-        @ActionType
-        private final String mType;
-        @NonNull
-        private final CharSequence mTextReply;
-        @Nullable
-        private final RemoteAction mAction;
-
-        @FloatRange(from = 0, to = 1)
-        private final float mScore;
-
-        @NonNull
-        private final Bundle mExtras;
-
-        private ConversationAction(
-                @NonNull String type,
-                @Nullable RemoteAction action,
-                @Nullable CharSequence textReply,
-                float score,
-                @NonNull Bundle extras) {
-            mType = Preconditions.checkNotNull(type);
-            mAction = action;
-            mTextReply = textReply;
-            mScore = score;
-            mExtras = Preconditions.checkNotNull(extras);
-        }
-
-        private ConversationAction(Parcel in) {
-            mType = in.readString();
-            mAction = in.readParcelable(null);
-            mTextReply = in.readCharSequence();
-            mScore = in.readFloat();
-            mExtras = in.readBundle();
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int flags) {
-            parcel.writeString(mType);
-            parcel.writeParcelable(mAction, flags);
-            parcel.writeCharSequence(mTextReply);
-            parcel.writeFloat(mScore);
-            parcel.writeBundle(mExtras);
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @NonNull
-        @ActionType
-        /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */
-        public String getType() {
-            return mType;
-        }
-
-        @Nullable
-        /**
-         * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for
-         * the specified action type.
-         */
-        public RemoteAction getAction() {
-            return mAction;
-        }
-
-        /**
-         * Returns the confidence score for the specified action. The value ranges from 0 (low
-         * confidence) to 1 (high confidence).
-         */
-        @FloatRange(from = 0, to = 1)
-        public float getConfidenceScore() {
-            return mScore;
-        }
-
-        /**
-         * Returns the text reply that could be sent as a reply to the given conversation.
-         * <p>
-         * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}.
-         */
-        @Nullable
-        public CharSequence getTextReply() {
-            return mTextReply;
-        }
-
-        /**
-         * Returns the extended data related to this conversation action.
-         *
-         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
-         * prefer to hold a reference to the returned bundle rather than frequently calling this
-         * method.
-         */
-        @NonNull
-        public Bundle getExtras() {
-            return mExtras.deepCopy();
-        }
-
-        /** Builder class to construct {@link ConversationAction}. */
-        public static final class Builder {
-            @Nullable
-            @ActionType
-            private String mType;
-            @Nullable
-            private RemoteAction mAction;
-            @Nullable
-            private CharSequence mTextReply;
-            private float mScore;
-            @Nullable
-            private Bundle mExtras;
-
-            public Builder(@NonNull @ActionType String actionType) {
-                mType = Preconditions.checkNotNull(actionType);
-            }
-
-            /**
-             * Sets an action that may be performed on the given conversation.
-             */
-            @NonNull
-            public Builder setAction(@Nullable RemoteAction action) {
-                mAction = action;
-                return this;
-            }
-
-            /**
-             * Sets a text reply that may be performed on the given conversation.
-             */
-            @NonNull
-            public Builder setTextReply(@Nullable CharSequence textReply) {
-                mTextReply = textReply;
-                return this;
-            }
-
-            /** Sets the confident score. */
-            @NonNull
-            public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) {
-                mScore = score;
-                return this;
-            }
-
-            /**
-             * Sets the extended data for the conversation action object.
-             */
-            @NonNull
-            public Builder setExtras(@Nullable Bundle extras) {
-                mExtras = extras;
-                return this;
-            }
-
-            /** Builds the {@link ConversationAction} object. */
-            @NonNull
-            public ConversationAction build() {
-                return new ConversationAction(
-                        mType,
-                        mAction,
-                        mTextReply,
-                        mScore,
-                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
-            }
-        }
-    }
-
     /** Represents a message in the conversation. */
     public static final class Message implements Parcelable {
         /**
@@ -538,156 +280,36 @@
         }
     }
 
-    /** Configuration object for specifying what action types to identify. */
-    public static final class TypeConfig implements Parcelable {
-        @NonNull
-        @ActionType
-        private final Set<String> mExcludedTypes;
-        @NonNull
-        @ActionType
-        private final Set<String> mIncludedTypes;
-        private final boolean mIncludeTypesFromTextClassifier;
-
-        private TypeConfig(
-                @NonNull Set<String> includedTypes,
-                @NonNull Set<String> excludedTypes,
-                boolean includeTypesFromTextClassifier) {
-            mIncludedTypes = Preconditions.checkNotNull(includedTypes);
-            mExcludedTypes = Preconditions.checkNotNull(excludedTypes);
-            mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
-        }
-
-        private TypeConfig(Parcel in) {
-            mIncludedTypes = new ArraySet<>(in.createStringArrayList());
-            mExcludedTypes = new ArraySet<>(in.createStringArrayList());
-            mIncludeTypesFromTextClassifier = in.readByte() != 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int flags) {
-            parcel.writeStringList(new ArrayList<>(mIncludedTypes));
-            parcel.writeStringList(new ArrayList<>(mExcludedTypes));
-            parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0));
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        public static final Creator<TypeConfig> CREATOR =
-                new Creator<TypeConfig>() {
-                    @Override
-                    public TypeConfig createFromParcel(Parcel in) {
-                        return new TypeConfig(in);
-                    }
-
-                    @Override
-                    public TypeConfig[] newArray(int size) {
-                        return new TypeConfig[size];
-                    }
-                };
-
-        /**
-         * Returns a final list of types that the text classifier should look for.
-         *
-         * <p>NOTE: This method is intended for use by a text classifier.
-         *
-         * @param defaultTypes types the text classifier thinks should be included before factoring
-         *    in the included/excluded types given by the client.
-         */
-        @NonNull
-        public Collection<String> resolveTypes(@Nullable Collection<String> defaultTypes) {
-            Set<String> types = new ArraySet<>();
-            if (mIncludeTypesFromTextClassifier && defaultTypes != null) {
-                types.addAll(defaultTypes);
-            }
-            types.addAll(mIncludedTypes);
-            types.removeAll(mExcludedTypes);
-            return Collections.unmodifiableCollection(types);
-        }
-
-        /**
-         * Return whether the client allows the text classifier to include its own list of default
-         * types. If this function returns {@code true}, the text classifier can consider specifying
-         * a default list of entity types in {@link #resolveTypes(Collection)}.
-         *
-         * <p>NOTE: This method is intended for use by a text classifier.
-         *
-         * @see #resolveTypes(Collection)
-         */
-        public boolean shouldIncludeTypesFromTextClassifier() {
-            return mIncludeTypesFromTextClassifier;
-        }
-
-        /** Builder class to construct the {@link TypeConfig} object. */
-        public static final class Builder {
-            @Nullable
-            private Collection<String> mExcludedTypes;
-            @Nullable
-            private Collection<String> mIncludedTypes;
-            private boolean mIncludeTypesFromTextClassifier = true;
-
-            /**
-             * Sets a collection of types that are explicitly included, for example, {@link
-             * #TYPE_VIEW_CALENDAR}.
-             */
-            @NonNull
-            public Builder setIncludedTypes(
-                    @Nullable @ActionType Collection<String> includedTypes) {
-                mIncludedTypes = includedTypes;
-                return this;
-            }
-
-            /**
-             * Sets a collection of types that are explicitly excluded, for example, {@link
-             * #TYPE_VIEW_CALENDAR}.
-             */
-            @NonNull
-            public Builder setExcludedTypes(
-                    @Nullable @ActionType Collection<String> excludedTypes) {
-                mExcludedTypes = excludedTypes;
-                return this;
-            }
-
-            /**
-             * Specifies whether or not to include the types suggested by the text classifier. By
-             * default, it is included.
-             */
-            @NonNull
-            public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) {
-                mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
-                return this;
-            }
-
-            /**
-             * Combines all of the options that have been set and returns a new {@link TypeConfig}
-             * object.
-             */
-            @NonNull
-            public TypeConfig build() {
-                return new TypeConfig(
-                        mIncludedTypes == null
-                                ? Collections.emptySet()
-                                : new ArraySet<>(mIncludedTypes),
-                        mExcludedTypes == null
-                                ? Collections.emptySet()
-                                : new ArraySet<>(mExcludedTypes),
-                        mIncludeTypesFromTextClassifier);
-            }
-        }
-    }
-
     /**
      * A request object for generating conversation action suggestions.
      *
      * @see TextClassifier#suggestConversationActions(Request)
      */
     public static final class Request implements Parcelable {
+
+        /** @hide */
+        @Retention(SOURCE)
+        @StringDef(
+                value = {
+                        HINT_FOR_NOTIFICATION,
+                        HINT_FOR_IN_APP,
+                },
+                prefix = "HINT_")
+        public @interface Hint {}
+
+        /**
+         * To indicate the generated actions will be used within the app.
+         */
+        public static final String HINT_FOR_IN_APP = "in_app";
+        /**
+         * To indicate the generated actions will be used for notification.
+         */
+        public static final String HINT_FOR_NOTIFICATION = "notification";
+
         @NonNull
         private final List<Message> mConversation;
         @NonNull
-        private final TypeConfig mTypeConfig;
+        private final TextClassifier.EntityConfig mTypeConfig;
         private final int mMaxSuggestions;
         @NonNull
         @Hint
@@ -699,7 +321,7 @@
 
         private Request(
                 @NonNull List<Message> conversation,
-                @NonNull TypeConfig typeConfig,
+                @NonNull TextClassifier.EntityConfig typeConfig,
                 int maxSuggestions,
                 String conversationId,
                 @Nullable @Hint List<String> hints) {
@@ -713,7 +335,7 @@
         private static Request readFromParcel(Parcel in) {
             List<Message> conversation = new ArrayList<>();
             in.readParcelableList(conversation, null);
-            TypeConfig typeConfig = in.readParcelable(null);
+            TextClassifier.EntityConfig typeConfig = in.readParcelable(null);
             int maxSuggestions = in.readInt();
             String conversationId = in.readString();
             List<String> hints = new ArrayList<>();
@@ -760,7 +382,7 @@
 
         /** Returns the type config. */
         @NonNull
-        public TypeConfig getTypeConfig() {
+        public TextClassifier.EntityConfig getTypeConfig() {
             return mTypeConfig;
         }
 
@@ -820,7 +442,7 @@
             @NonNull
             private List<Message> mConversation;
             @Nullable
-            private TypeConfig mTypeConfig;
+            private TextClassifier.EntityConfig mTypeConfig;
             private int mMaxSuggestions;
             @Nullable
             private String mConversationId;
@@ -849,7 +471,7 @@
 
             /** Sets the type config. */
             @NonNull
-            public Builder setTypeConfig(@Nullable TypeConfig typeConfig) {
+            public Builder setTypeConfig(@Nullable TextClassifier.EntityConfig typeConfig) {
                 mTypeConfig = typeConfig;
                 return this;
             }
@@ -879,7 +501,9 @@
             public Request build() {
                 return new Request(
                         Collections.unmodifiableList(mConversation),
-                        mTypeConfig == null ? new TypeConfig.Builder().build() : mTypeConfig,
+                        mTypeConfig == null
+                                ? new TextClassifier.EntityConfig.Builder().build()
+                                : mTypeConfig,
                         mMaxSuggestions,
                         mConversationId,
                         mHints == null
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 50801a2..ce680ec 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -117,15 +117,15 @@
             .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString();
     private static final String CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES =
             new StringJoiner(ENTITY_LIST_DELIMITER)
-                    .add(ConversationActions.TYPE_TEXT_REPLY)
-                    .add(ConversationActions.TYPE_CREATE_REMINDER)
-                    .add(ConversationActions.TYPE_CALL_PHONE)
-                    .add(ConversationActions.TYPE_OPEN_URL)
-                    .add(ConversationActions.TYPE_SEND_EMAIL)
-                    .add(ConversationActions.TYPE_SEND_SMS)
-                    .add(ConversationActions.TYPE_TRACK_FLIGHT)
-                    .add(ConversationActions.TYPE_VIEW_CALENDAR)
-                    .add(ConversationActions.TYPE_VIEW_MAP)
+                    .add(ConversationAction.TYPE_TEXT_REPLY)
+                    .add(ConversationAction.TYPE_CREATE_REMINDER)
+                    .add(ConversationAction.TYPE_CALL_PHONE)
+                    .add(ConversationAction.TYPE_OPEN_URL)
+                    .add(ConversationAction.TYPE_SEND_EMAIL)
+                    .add(ConversationAction.TYPE_SEND_SMS)
+                    .add(ConversationAction.TYPE_TRACK_FLIGHT)
+                    .add(ConversationAction.TYPE_VIEW_CALENDAR)
+                    .add(ConversationAction.TYPE_VIEW_MAP)
                     .toString();
 
     private final boolean mSystemTextClassifierEnabled;
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 8709e09..5a56136 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -32,7 +32,6 @@
 import android.text.util.Linkify;
 import android.text.util.Linkify.LinkifyMask;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
@@ -43,6 +42,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -324,7 +324,7 @@
     }
 
     /**
-     * Detects the language of the specified text.
+     * Detects the language of the text in the given request.
      *
      * <p><strong>NOTE: </strong>Call on a worker thread.
      *
@@ -403,42 +403,59 @@
     default void dump(@NonNull IndentingPrintWriter printWriter) {}
 
     /**
-     * Configuration object for specifying what entities to identify.
+     * Configuration object for specifying what entity types to identify.
      *
      * Configs are initially based on a predefined preset, and can be modified from there.
      */
     final class EntityConfig implements Parcelable {
-        private final Collection<String> mHints;
-        private final Collection<String> mExcludedEntityTypes;
-        private final Collection<String> mIncludedEntityTypes;
-        private final boolean mUseHints;
+        private final List<String> mIncludedTypes;
+        private final List<String> mExcludedTypes;
+        private final List<String> mHints;
+        private final boolean mIncludeTypesFromTextClassifier;
 
-        private EntityConfig(boolean useHints, Collection<String> hints,
-                Collection<String> includedEntityTypes, Collection<String> excludedEntityTypes) {
-            mHints = hints == null
-                    ? Collections.EMPTY_LIST
-                    : Collections.unmodifiableCollection(new ArraySet<>(hints));
-            mExcludedEntityTypes = excludedEntityTypes == null
-                    ? Collections.EMPTY_LIST : new ArraySet<>(excludedEntityTypes);
-            mIncludedEntityTypes = includedEntityTypes == null
-                    ? Collections.EMPTY_LIST : new ArraySet<>(includedEntityTypes);
-            mUseHints = useHints;
+        private EntityConfig(
+                List<String> includedEntityTypes,
+                List<String> excludedEntityTypes,
+                List<String> hints,
+                boolean includeTypesFromTextClassifier) {
+            mIncludedTypes = Preconditions.checkNotNull(includedEntityTypes);
+            mExcludedTypes = Preconditions.checkNotNull(excludedEntityTypes);
+            mHints = Preconditions.checkNotNull(hints);
+            mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
+        }
+
+        private EntityConfig(Parcel in) {
+            mIncludedTypes = new ArrayList<>();
+            in.readStringList(mIncludedTypes);
+            mExcludedTypes = new ArrayList<>();
+            in.readStringList(mExcludedTypes);
+            List<String> tmpHints = new ArrayList<>();
+            in.readStringList(tmpHints);
+            mHints = Collections.unmodifiableList(tmpHints);
+            mIncludeTypesFromTextClassifier = in.readByte() != 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeStringList(mIncludedTypes);
+            parcel.writeStringList(mExcludedTypes);
+            parcel.writeStringList(mHints);
+            parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0));
         }
 
         /**
          * Creates an EntityConfig.
          *
          * @param hints Hints for the TextClassifier to determine what types of entities to find.
+         *
+         * @deprecated Use {@link Builder} instead.
          */
+        @Deprecated
         public static EntityConfig createWithHints(@Nullable Collection<String> hints) {
-            return new EntityConfig(/* useHints */ true, hints,
-                    /* includedEntityTypes */null, /* excludedEntityTypes */ null);
-        }
-
-        // TODO: Remove once apps can build against the latest sdk.
-        /** @hide */
-        public static EntityConfig create(@Nullable Collection<String> hints) {
-            return createWithHints(hints);
+            return new EntityConfig.Builder()
+                    .includeTypesFromTextClassifier(true)
+                    .setHints(hints)
+                    .build();
         }
 
         /**
@@ -450,12 +467,19 @@
          *
          *
          * Note that if an entity has been excluded, the exclusion will take precedence.
+         *
+         * @deprecated Use {@link Builder} instead.
          */
+        @Deprecated
         public static EntityConfig create(@Nullable Collection<String> hints,
                 @Nullable Collection<String> includedEntityTypes,
                 @Nullable Collection<String> excludedEntityTypes) {
-            return new EntityConfig(/* useHints */ true, hints,
-                    includedEntityTypes, excludedEntityTypes);
+            return new EntityConfig.Builder()
+                    .setIncludedTypes(includedEntityTypes)
+                    .setExcludedTypes(excludedEntityTypes)
+                    .setHints(hints)
+                    .includeTypesFromTextClassifier(true)
+                    .build();
         }
 
         /**
@@ -463,34 +487,33 @@
          *
          * @param entityTypes Complete set of entities, e.g. {@link #TYPE_URL} to find.
          *
+         * @deprecated Use {@link Builder} instead.
          */
+        @Deprecated
         public static EntityConfig createWithExplicitEntityList(
                 @Nullable Collection<String> entityTypes) {
-            return new EntityConfig(/* useHints */ false, /* hints */ null,
-                    /* includedEntityTypes */ entityTypes, /* excludedEntityTypes */ null);
-        }
-
-        // TODO: Remove once apps can build against the latest sdk.
-        /** @hide */
-        public static EntityConfig createWithEntityList(@Nullable Collection<String> entityTypes) {
-            return createWithExplicitEntityList(entityTypes);
+            return new EntityConfig.Builder()
+                    .setIncludedTypes(entityTypes)
+                    .includeTypesFromTextClassifier(false)
+                    .build();
         }
 
         /**
-         * Returns a list of the final set of entities to find.
+         * Returns a final list of entity types to find.
          *
-         * @param entities Entities we think should be found before factoring in includes/excludes
+         * @param entityTypes Entity types we think should be found before factoring in
+         *                    includes/excludes
          *
          * This method is intended for use by TextClassifier implementations.
          */
         public Collection<String> resolveEntityListModifications(
-                @NonNull Collection<String> entities) {
-            final Set<String> finalSet = new HashSet();
-            if (mUseHints) {
-                finalSet.addAll(entities);
+                @NonNull Collection<String> entityTypes) {
+            final Set<String> finalSet = new HashSet<>();
+            if (mIncludeTypesFromTextClassifier) {
+                finalSet.addAll(entityTypes);
             }
-            finalSet.addAll(mIncludedEntityTypes);
-            finalSet.removeAll(mExcludedEntityTypes);
+            finalSet.addAll(mIncludedTypes);
+            finalSet.removeAll(mExcludedTypes);
             return finalSet;
         }
 
@@ -503,17 +526,22 @@
             return mHints;
         }
 
-        @Override
-        public int describeContents() {
-            return 0;
+        /**
+         * Return whether the client allows the text classifier to include its own list of
+         * default types. If this function returns {@code true}, a default list of types suggested
+         * from a text classifier will be taking into account.
+         *
+         * <p>NOTE: This method is intended for use by a text classifier.
+         *
+         * @see #resolveEntityListModifications(Collection)
+         */
+        public boolean shouldIncludeTypesFromTextClassifier() {
+            return mIncludeTypesFromTextClassifier;
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeStringList(new ArrayList<>(mHints));
-            dest.writeStringList(new ArrayList<>(mExcludedEntityTypes));
-            dest.writeStringList(new ArrayList<>(mIncludedEntityTypes));
-            dest.writeInt(mUseHints ? 1 : 0);
+        public int describeContents() {
+            return 0;
         }
 
         public static final Parcelable.Creator<EntityConfig> CREATOR =
@@ -529,11 +557,75 @@
                     }
                 };
 
-        private EntityConfig(Parcel in) {
-            mHints = new ArraySet<>(in.createStringArrayList());
-            mExcludedEntityTypes = new ArraySet<>(in.createStringArrayList());
-            mIncludedEntityTypes = new ArraySet<>(in.createStringArrayList());
-            mUseHints = in.readInt() == 1;
+
+
+        /** Builder class to construct the {@link EntityConfig} object. */
+        public static final class Builder {
+            @Nullable
+            private Collection<String> mIncludedTypes;
+            @Nullable
+            private Collection<String> mExcludedTypes;
+            @Nullable
+            private Collection<String> mHints;
+            private boolean mIncludeTypesFromTextClassifier = true;
+
+            /**
+             * Sets a collection of types that are explicitly included.
+             */
+            @NonNull
+            public Builder setIncludedTypes(@Nullable Collection<String> includedTypes) {
+                mIncludedTypes = includedTypes;
+                return this;
+            }
+
+            /**
+             * Sets a collection of types that are explicitly excluded.
+             */
+            @NonNull
+            public Builder setExcludedTypes(@Nullable Collection<String> excludedTypes) {
+                mExcludedTypes = excludedTypes;
+                return this;
+            }
+
+            /**
+             * Specifies whether or not to include the types suggested by the text classifier. By
+             * default, it is included.
+             */
+            @NonNull
+            public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) {
+                mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
+                return this;
+            }
+
+
+            /**
+             * Sets the hints for the TextClassifier to determine what types of entities to find.
+             * These hints will only be used if {@link #includeTypesFromTextClassifier} is
+             * set to be true.
+             */
+            public Builder setHints(Collection<String> hints) {
+                mHints = hints;
+                return this;
+            }
+
+            /**
+             * Combines all of the options that have been set and returns a new {@link EntityConfig}
+             * object.
+             */
+            @NonNull
+            public EntityConfig build() {
+                return new EntityConfig(
+                        mIncludedTypes == null
+                                ? Collections.emptyList()
+                                : new ArrayList<>(mIncludedTypes),
+                        mExcludedTypes == null
+                                ? Collections.emptyList()
+                                : new ArrayList<>(mExcludedTypes),
+                        mHints == null
+                                ? Collections.emptyList()
+                                : Collections.unmodifiableList(new ArrayList<>(mHints)),
+                        mIncludeTypesFromTextClassifier);
+            }
         }
     }
 
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index d5b9eb1..9ab963e 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -393,7 +393,7 @@
                     actionsImpl.suggestActions(nativeConversation, null);
 
             Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
-            List<ConversationActions.ConversationAction> conversationActions = new ArrayList<>();
+            List<ConversationAction> conversationActions = new ArrayList<>();
             int maxSuggestions = nativeSuggestions.length;
             if (request.getMaxSuggestions() > 0) {
                 maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length);
@@ -405,7 +405,7 @@
                     continue;
                 }
                 conversationActions.add(
-                        new ConversationActions.ConversationAction.Builder(actionType)
+                        new ConversationAction.Builder(actionType)
                                 .setTextReply(nativeSuggestion.getResponseText())
                                 .setConfidenceScore(nativeSuggestion.getScore())
                                 .build());
@@ -445,10 +445,10 @@
 
     private Collection<String> resolveActionTypesFromRequest(ConversationActions.Request request) {
         List<String> defaultActionTypes =
-                request.getHints().contains(ConversationActions.HINT_FOR_NOTIFICATION)
+                request.getHints().contains(ConversationActions.Request.HINT_FOR_NOTIFICATION)
                         ? mSettings.getNotificationConversationActionTypes()
                         : mSettings.getInAppConversationActionTypes();
-        return request.getTypeConfig().resolveTypes(defaultActionTypes);
+        return request.getTypeConfig().resolveEntityListModifications(defaultActionTypes);
     }
 
     private AnnotatorModel getAnnotatorImpl(LocaleList localeList)
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 9b9b771..8e88c51 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -23,6 +23,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.service.procstats.ProcessStatsAvailablePagesProto;
 import android.service.procstats.ProcessStatsPackageProto;
 import android.service.procstats.ProcessStatsSectionProto;
 import android.text.format.DateFormat;
@@ -178,7 +179,7 @@
             {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};
 
     // Current version of the parcel format.
-    private static final int PARCEL_VERSION = 35;
+    private static final int PARCEL_VERSION = 36;
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0x50535454;
 
@@ -237,10 +238,11 @@
     ArrayList<String> mIndexToCommonString;
 
     private static final Pattern sPageTypeRegex = Pattern.compile(
-            "^Node\\s+(\\d+),.*. type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$");
-    private final ArrayList<Integer> mPageTypeZones = new ArrayList<Integer>();
-    private final ArrayList<String> mPageTypeLabels = new ArrayList<String>();
-    private final ArrayList<int[]> mPageTypeSizes = new ArrayList<int[]>();
+            "^Node\\s+(\\d+),.* zone\\s+(\\w+),.* type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$");
+    private final ArrayList<Integer> mPageTypeNodes = new ArrayList<>();
+    private final ArrayList<String> mPageTypeZones = new ArrayList<>();
+    private final ArrayList<String> mPageTypeLabels = new ArrayList<>();
+    private final ArrayList<int[]> mPageTypeSizes = new ArrayList<>();
 
     public ProcessStats(boolean running) {
         mRunning = running;
@@ -621,6 +623,7 @@
         try {
             reader = new BufferedReader(new FileReader("/proc/pagetypeinfo"));
             final Matcher matcher = sPageTypeRegex.matcher("");
+            mPageTypeNodes.clear();
             mPageTypeZones.clear();
             mPageTypeLabels.clear();
             mPageTypeSizes.clear();
@@ -631,16 +634,18 @@
                 }
                 matcher.reset(line);
                 if (matcher.matches()) {
-                    final Integer zone = Integer.valueOf(matcher.group(1), 10);
-                    if (zone == null) {
+                    final Integer node = Integer.valueOf(matcher.group(1), 10);
+                    if (node == null) {
                         continue;
                     }
-                    mPageTypeZones.add(zone);
-                    mPageTypeLabels.add(matcher.group(2));
-                    mPageTypeSizes.add(splitAndParseNumbers(matcher.group(3)));
+                    mPageTypeNodes.add(node);
+                    mPageTypeZones.add(matcher.group(2));
+                    mPageTypeLabels.add(matcher.group(3));
+                    mPageTypeSizes.add(splitAndParseNumbers(matcher.group(4)));
                 }
             }
         } catch (IOException ex) {
+            mPageTypeNodes.clear();
             mPageTypeZones.clear();
             mPageTypeLabels.clear();
             mPageTypeSizes.clear();
@@ -935,7 +940,8 @@
         final int NPAGETYPES = mPageTypeLabels.size();
         out.writeInt(NPAGETYPES);
         for (int i=0; i<NPAGETYPES; i++) {
-            out.writeInt(mPageTypeZones.get(i));
+            out.writeInt(mPageTypeNodes.get(i));
+            out.writeString(mPageTypeZones.get(i));
             out.writeString(mPageTypeLabels.get(i));
             out.writeIntArray(mPageTypeSizes.get(i));
         }
@@ -1244,6 +1250,8 @@
 
         // Fragmentation info
         final int NPAGETYPES = in.readInt();
+        mPageTypeNodes.clear();
+        mPageTypeNodes.ensureCapacity(NPAGETYPES);
         mPageTypeZones.clear();
         mPageTypeZones.ensureCapacity(NPAGETYPES);
         mPageTypeLabels.clear();
@@ -1251,7 +1259,8 @@
         mPageTypeSizes.clear();
         mPageTypeSizes.ensureCapacity(NPAGETYPES);
         for (int i=0; i<NPAGETYPES; i++) {
-            mPageTypeZones.add(in.readInt());
+            mPageTypeNodes.add(in.readInt());
+            mPageTypeZones.add(in.readString());
             mPageTypeLabels.add(in.readString());
             mPageTypeSizes.add(in.createIntArray());
         }
@@ -1764,7 +1773,8 @@
         pw.println("Available pages by page size:");
         final int NPAGETYPES = mPageTypeLabels.size();
         for (int i=0; i<NPAGETYPES; i++) {
-            pw.format("Zone %3d  %14s ", mPageTypeZones.get(i), mPageTypeLabels.get(i));
+            pw.format("Node %3d Zone %7s  %14s ", mPageTypeNodes.get(i), mPageTypeZones.get(i),
+                    mPageTypeLabels.get(i));
             final int[] sizes = mPageTypeSizes.get(i);
             final int N = sizes == null ? 0 : sizes.length;
             for (int j=0; j<N; j++) {
@@ -2095,6 +2105,9 @@
             pw.print(",");
             pw.print(mPageTypeZones.get(i));
             pw.print(",");
+            // Wasn't included in original output.
+            //pw.print(mPageTypeNodes.get(i));
+            //pw.print(",");
             final int[] sizes = mPageTypeSizes.get(i);
             final int N = sizes == null ? 0 : sizes.length;
             for (int j=0; j<N; j++) {
@@ -2135,6 +2148,20 @@
             proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
         }
 
+        final int NPAGETYPES = mPageTypeLabels.size();
+        for (int i = 0; i < NPAGETYPES; i++) {
+            final long token = proto.start(ProcessStatsSectionProto.AVAILABLE_PAGES);
+            proto.write(ProcessStatsAvailablePagesProto.NODE, mPageTypeNodes.get(i));
+            proto.write(ProcessStatsAvailablePagesProto.ZONE, mPageTypeZones.get(i));
+            proto.write(ProcessStatsAvailablePagesProto.LABEL, mPageTypeLabels.get(i));
+            final int[] sizes = mPageTypeSizes.get(i);
+            final int N = sizes == null ? 0 : sizes.length;
+            for (int j = 0; j < N; j++) {
+                proto.write(ProcessStatsAvailablePagesProto.PAGES_PER_ORDER, sizes[j]);
+            }
+            proto.end(token);
+        }
+
         final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
         if ((section & REPORT_PROC_STATS) != 0) {
             for (int ip = 0; ip < procMap.size(); ip++) {
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index eb7338a..876bd4f 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -8,7 +8,6 @@
 #include "SkImageInfo.h"
 #include "SkColor.h"
 #include "SkColorSpace.h"
-#include "SkMatrix44.h"
 #include "GraphicsJNI.h"
 #include "SkStream.h"
 
@@ -356,8 +355,8 @@
     if (xyzD50 == nullptr || transferParameters == nullptr) {
         colorSpace = SkColorSpace::MakeSRGB();
     } else {
-        SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
-        SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
+        skcms_TransferFunction p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
+        skcms_Matrix3x3 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
         colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
     }
 
@@ -549,8 +548,7 @@
     if (skbitmap.colorType() == kRGBA_F16_SkColorType) {
         // Convert to P3 before encoding. This matches SkAndroidCodec::computeOutputColorSpace
         // for wide gamuts.
-        auto cs = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                        SkColorSpace::kDCIP3_D65_Gamut);
+        auto cs = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
         auto info = skbitmap.info().makeColorType(kRGBA_8888_SkColorType)
                                    .makeColorSpace(std::move(cs));
         SkBitmap p3;
@@ -568,11 +566,34 @@
     return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
 }
 
+static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color,
+        const sk_sp<SkColorSpace>& colorSpace) {
+    SkPaint p;
+    p.setColor4f(color, colorSpace.get());
+    p.setBlendMode(SkBlendMode::kSrc);
+    SkCanvas canvas(bitmap);
+    canvas.drawPaint(p);
+}
+
 static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
     LocalScopedBitmap bitmap(bitmapHandle);
     SkBitmap skBitmap;
     bitmap->getSkBitmap(&skBitmap);
-    skBitmap.eraseColor(color);
+    bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
+}
+
+static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle, jobject jColorSpace,
+        jfloat r, jfloat g, jfloat b, jfloat a) {
+    sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace);
+    if (GraphicsJNI::hasException(env)) {
+        return;
+    }
+
+    LocalScopedBitmap bitmap(bitmapHandle);
+    SkBitmap skBitmap;
+    bitmap->getSkBitmap(&skBitmap);
+    SkColor4f color = SkColor4f{r, g, b, a};
+    bitmapErase(skBitmap, color, cs);
 }
 
 static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -717,7 +738,7 @@
 #endif
         // Dup the file descriptor so we can keep a reference to it after the Parcel
         // is disposed.
-        int dupFd = dup(blob.fd());
+        int dupFd = fcntl(blob.fd(), F_DUPFD_CLOEXEC, 0);
         if (dupFd < 0) {
             ALOGE("Error allocating dup fd. Error:%d", errno);
             blob.release();
@@ -910,32 +931,32 @@
     SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
     if (colorSpace == nullptr) return JNI_FALSE;
 
-    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+    skcms_Matrix3x3 xyzMatrix;
     if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
 
     jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
-    xyz[0] = xyzMatrix.getFloat(0, 0);
-    xyz[1] = xyzMatrix.getFloat(1, 0);
-    xyz[2] = xyzMatrix.getFloat(2, 0);
-    xyz[3] = xyzMatrix.getFloat(0, 1);
-    xyz[4] = xyzMatrix.getFloat(1, 1);
-    xyz[5] = xyzMatrix.getFloat(2, 1);
-    xyz[6] = xyzMatrix.getFloat(0, 2);
-    xyz[7] = xyzMatrix.getFloat(1, 2);
-    xyz[8] = xyzMatrix.getFloat(2, 2);
+    xyz[0] = xyzMatrix.vals[0][0];
+    xyz[1] = xyzMatrix.vals[1][0];
+    xyz[2] = xyzMatrix.vals[2][0];
+    xyz[3] = xyzMatrix.vals[0][1];
+    xyz[4] = xyzMatrix.vals[1][1];
+    xyz[5] = xyzMatrix.vals[2][1];
+    xyz[6] = xyzMatrix.vals[0][2];
+    xyz[7] = xyzMatrix.vals[1][2];
+    xyz[8] = xyzMatrix.vals[2][2];
     env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
 
-    SkColorSpaceTransferFn transferParams;
+    skcms_TransferFunction transferParams;
     if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
 
     jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
-    params[0] = transferParams.fA;
-    params[1] = transferParams.fB;
-    params[2] = transferParams.fC;
-    params[3] = transferParams.fD;
-    params[4] = transferParams.fE;
-    params[5] = transferParams.fF;
-    params[6] = transferParams.fG;
+    params[0] = transferParams.a;
+    params[1] = transferParams.b;
+    params[2] = transferParams.c;
+    params[3] = transferParams.d;
+    params[4] = transferParams.e;
+    params[5] = transferParams.f;
+    params[6] = transferParams.g;
     env->ReleaseFloatArrayElements(paramsArray, params, 0);
 
     return JNI_TRUE;
@@ -1121,8 +1142,8 @@
 
 static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
                                                jfloatArray xyzD50, jobject transferParameters) {
-    SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
-    SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
+    skcms_TransferFunction p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
+    skcms_Matrix3x3 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
     sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
     AHardwareBuffer* hwBuf = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
         hardwareBuffer);
@@ -1183,6 +1204,7 @@
     {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
         (void*)Bitmap_compress },
     {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
+    {   "nativeErase",              "(JLandroid/graphics/ColorSpace;FFFF)V", (void*)Bitmap_eraseLong },
     {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
     {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
     {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 67d0c8a..9e74b88 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -424,30 +424,30 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkColorSpaceTransferFn GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) {
-    SkColorSpaceTransferFn p;
-    p.fA = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID);
-    p.fB = (float) env->GetDoubleField(transferParams, gTransferParams_bFieldID);
-    p.fC = (float) env->GetDoubleField(transferParams, gTransferParams_cFieldID);
-    p.fD = (float) env->GetDoubleField(transferParams, gTransferParams_dFieldID);
-    p.fE = (float) env->GetDoubleField(transferParams, gTransferParams_eFieldID);
-    p.fF = (float) env->GetDoubleField(transferParams, gTransferParams_fFieldID);
-    p.fG = (float) env->GetDoubleField(transferParams, gTransferParams_gFieldID);
+skcms_TransferFunction GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) {
+    skcms_TransferFunction p;
+    p.a = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID);
+    p.b = (float) env->GetDoubleField(transferParams, gTransferParams_bFieldID);
+    p.c = (float) env->GetDoubleField(transferParams, gTransferParams_cFieldID);
+    p.d = (float) env->GetDoubleField(transferParams, gTransferParams_dFieldID);
+    p.e = (float) env->GetDoubleField(transferParams, gTransferParams_eFieldID);
+    p.f = (float) env->GetDoubleField(transferParams, gTransferParams_fFieldID);
+    p.g = (float) env->GetDoubleField(transferParams, gTransferParams_gFieldID);
     return p;
 }
 
-SkMatrix44 GraphicsJNI::getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) {
-    SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor);
+skcms_Matrix3x3 GraphicsJNI::getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) {
+    skcms_Matrix3x3 xyzMatrix;
     jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
-    xyzMatrix.setFloat(0, 0, array[0]);
-    xyzMatrix.setFloat(1, 0, array[1]);
-    xyzMatrix.setFloat(2, 0, array[2]);
-    xyzMatrix.setFloat(0, 1, array[3]);
-    xyzMatrix.setFloat(1, 1, array[4]);
-    xyzMatrix.setFloat(2, 1, array[5]);
-    xyzMatrix.setFloat(0, 2, array[6]);
-    xyzMatrix.setFloat(1, 2, array[7]);
-    xyzMatrix.setFloat(2, 2, array[8]);
+    xyzMatrix.vals[0][0] = array[0];
+    xyzMatrix.vals[1][0] = array[1];
+    xyzMatrix.vals[2][0] = array[2];
+    xyzMatrix.vals[0][1] = array[3];
+    xyzMatrix.vals[1][1] = array[4];
+    xyzMatrix.vals[2][1] = array[5];
+    xyzMatrix.vals[0][2] = array[6];
+    xyzMatrix.vals[1][2] = array[7];
+    xyzMatrix.vals[2][2] = array[8];
     env->ReleaseFloatArrayElements(xyzD50, array, 0);
     return xyzMatrix;
 }
@@ -456,12 +456,14 @@
     if (colorSpace == nullptr) return nullptr;
     if (!env->IsInstanceOf(colorSpace, gColorSpaceRGB_class)) {
         doThrowIAE(env, "The color space must be an RGB color space");
+        return nullptr;
     }
 
     jobject transferParams = env->CallObjectMethod(colorSpace,
             gColorSpaceRGB_getTransferParametersMethodID);
     if (transferParams == nullptr) {
         doThrowIAE(env, "The color space must use an ICC parametric transfer function");
+        return nullptr;
     }
 
     jfloatArray illuminantD50 = (jfloatArray) env->GetStaticObjectField(gColorSpace_class,
@@ -472,8 +474,8 @@
     jfloatArray xyzD50 = (jfloatArray) env->CallObjectMethod(colorSpaceD50,
             gColorSpaceRGB_getTransformMethodID);
 
-    SkMatrix44 xyzMatrix = getNativeXYZMatrix(env, xyzD50);
-    SkColorSpaceTransferFn transferFunction = getNativeTransferParameters(env, transferParams);
+    skcms_Matrix3x3 xyzMatrix = getNativeXYZMatrix(env, xyzD50);
+    skcms_TransferFunction transferFunction = getNativeTransferParameters(env, transferParams);
 
     return SkColorSpace::MakeRGB(transferFunction, xyzMatrix);
 }
@@ -499,30 +501,30 @@
         } else if (decodeColorSpace.get() != nullptr) {
             // Try to match against known RGB color spaces using the CIE XYZ D50
             // conversion matrix and numerical transfer function parameters
-            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+            skcms_Matrix3x3 xyzMatrix;
             LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
 
-            SkColorSpaceTransferFn transferParams;
+            skcms_TransferFunction transferParams;
             // We can only handle numerical transfer functions at the moment
             LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
 
             jobject params = env->NewObject(gTransferParameters_class,
                     gTransferParameters_constructorMethodID,
-                    transferParams.fA, transferParams.fB, transferParams.fC,
-                    transferParams.fD, transferParams.fE, transferParams.fF,
-                    transferParams.fG);
+                    transferParams.a, transferParams.b, transferParams.c,
+                    transferParams.d, transferParams.e, transferParams.f,
+                    transferParams.g);
 
             jfloatArray xyzArray = env->NewFloatArray(9);
             jfloat xyz[9] = {
-                    xyzMatrix.getFloat(0, 0),
-                    xyzMatrix.getFloat(1, 0),
-                    xyzMatrix.getFloat(2, 0),
-                    xyzMatrix.getFloat(0, 1),
-                    xyzMatrix.getFloat(1, 1),
-                    xyzMatrix.getFloat(2, 1),
-                    xyzMatrix.getFloat(0, 2),
-                    xyzMatrix.getFloat(1, 2),
-                    xyzMatrix.getFloat(2, 2)
+                    xyzMatrix.vals[0][0],
+                    xyzMatrix.vals[1][0],
+                    xyzMatrix.vals[2][0],
+                    xyzMatrix.vals[0][1],
+                    xyzMatrix.vals[1][1],
+                    xyzMatrix.vals[2][1],
+                    xyzMatrix.vals[0][2],
+                    xyzMatrix.vals[1][2],
+                    xyzMatrix.vals[2][2]
             };
             env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
 
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index b0bd683..699d153 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -10,7 +10,6 @@
 #include "SkPoint.h"
 #include "SkRect.h"
 #include "SkColorSpace.h"
-#include "SkMatrix44.h"
 #include <jni.h>
 #include <hwui/Canvas.h>
 #include <hwui/Bitmap.h>
@@ -101,8 +100,8 @@
             int srcStride, int x, int y, int width, int height,
             SkBitmap* dstBitmap);
 
-    static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
-    static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
+    static skcms_TransferFunction getNativeTransferParameters(JNIEnv* env, jobject transferParams);
+    static skcms_Matrix3x3 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
     static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace);
 
     static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 7ef06dc..3b59321 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -473,7 +473,7 @@
     if (parcel != NULL) {
         int fd = parcel->readFileDescriptor();
         if (fd < 0) return NULL;
-        fd = dup(fd);
+        fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
         if (fd < 0) return NULL;
         return jniCreateFileDescriptor(env, fd);
     }
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 7b564ae..4101c04 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -44,6 +44,8 @@
 #include "androidfw/MutexGuard.h"
 #include "androidfw/PosixUtils.h"
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/ResourceUtils.h"
+
 #include "core_jni_helpers.h"
 #include "jni.h"
 #include "nativehelper/JNIHelp.h"
@@ -975,34 +977,7 @@
     return nullptr;
   }
 
-  std::string result;
-  if (name.package != nullptr) {
-    result.append(name.package, name.package_len);
-  }
-
-  if (name.type != nullptr || name.type16 != nullptr) {
-    if (!result.empty()) {
-      result += ":";
-    }
-
-    if (name.type != nullptr) {
-      result.append(name.type, name.type_len);
-    } else {
-      result += util::Utf16ToUtf8(StringPiece16(name.type16, name.type_len));
-    }
-  }
-
-  if (name.entry != nullptr || name.entry16 != nullptr) {
-    if (!result.empty()) {
-      result += "/";
-    }
-
-    if (name.entry != nullptr) {
-      result.append(name.entry, name.entry_len);
-    } else {
-      result += util::Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
-    }
-  }
+  std::string result = ToFormattedResourceString(&name);
   return env->NewStringUTF(result.c_str());
 }
 
@@ -1049,6 +1024,26 @@
   return nullptr;
 }
 
+static void NativeSetResourceResolutionLoggingEnabled(JNIEnv* /*env*/,
+                                                      jclass /*clazz*/,
+                                                      jlong ptr,
+                                                      jboolean enabled) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  assetmanager->SetResourceResolutionLoggingEnabled(enabled);
+}
+
+static jstring NativeGetLastResourceResolution(JNIEnv* env,
+                                               jclass /*clazz*/,
+                                               jlong ptr) {
+  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+  std::string resolution = assetmanager->GetLastResourceResolution();
+  if (resolution.empty()) {
+    return nullptr;
+  } else {
+    return env->NewStringUTF(resolution.c_str());
+  }
+}
+
 static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr,
                                      jboolean exclude_system) {
   ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
@@ -1452,6 +1447,10 @@
     {"nativeGetResourcePackageName", "(JI)Ljava/lang/String;", (void*)NativeGetResourcePackageName},
     {"nativeGetResourceTypeName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceTypeName},
     {"nativeGetResourceEntryName", "(JI)Ljava/lang/String;", (void*)NativeGetResourceEntryName},
+    {"nativeSetResourceResolutionLoggingEnabled", "(JZ)V",
+     (void*) NativeSetResourceResolutionLoggingEnabled},
+    {"nativeGetLastResourceResolution", "(J)Ljava/lang/String;",
+     (void*) NativeGetLastResourceResolution},
     {"nativeGetLocales", "(JZ)[Ljava/lang/String;", (void*)NativeGetLocales},
     {"nativeGetSizeConfigurations", "(J)[Landroid/content/res/Configuration;",
      (void*)NativeGetSizeConfigurations},
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index bd87dcc..41e00b9 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -33,6 +33,7 @@
 
 // Static whitelist of open paths that the zygote is allowed to keep open.
 static const char* kPathWhitelist[] = {
+  "/apex/com.android.conscrypt/javalib/conscrypt.jar",
   "/dev/null",
   "/dev/socket/zygote",
   "/dev/socket/zygote_secondary",
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 3e1c5a3..2f2f623 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -29,6 +29,12 @@
 
     // ACTION: Settings > Any preference is changed
     ACTION_SETTINGS_PREFERENCE_CHANGE = 853;
+
+    // ACTION: Tap & Pay -> Default Application Setting -> Use Forground
+    ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622;
+
+    // ACTION: Tap & Pay -> Default Application Setting -> Use Default
+    ACTION_NFC_PAYMENT_ALWAYS_SETTING = 1623;
 }
 
 /**
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 4ecf52c..7f96d70 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -111,6 +111,7 @@
         optional EnabledState enabled_state = 7;
         optional string last_disabled_app_caller = 8;
         optional string suspending_package = 9;
+        optional int32 distraction_flags = 10;
     }
 
     // Name of package. e.g. "com.android.providers.telephony".
diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto
index 71ebcc1..da801ff 100644
--- a/core/proto/android/service/procstats.proto
+++ b/core/proto/android/service/procstats.proto
@@ -43,7 +43,7 @@
  * Data model from /frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
  * This proto is defined based on the writeToParcel method.
  *
- * Next Tag: 10
+ * Next Tag: 11
  */
 message ProcessStatsSectionProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -76,6 +76,9 @@
     }
     repeated Status status = 7;
 
+    // Number of pages available of various types and sizes, representation fragmentation.
+    repeated ProcessStatsAvailablePagesProto available_pages = 10;
+
     // Stats for each process.
     repeated ProcessStatsProto process_stats = 8;
 
@@ -83,6 +86,24 @@
     repeated ProcessStatsPackageProto package_stats = 9;
 }
 
+// Next Tag: 5
+message ProcessStatsAvailablePagesProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // Node these pages are in (as per /proc/pagetypeinfo)
+    optional int32 node = 1;
+
+    // Zone these pages are in (as per /proc/pagetypeinfo)
+    optional string zone = 2;
+
+    // Label for the type of these pages (as per /proc/pagetypeinfo)
+    optional string label = 3;
+
+    // Distribution of number of pages available by order size.  First entry in array is
+    // order 0, second is order 1, etc.  Each order increase is a doubling of page size.
+    repeated int32 pages_per_order = 4;
+}
+
 // Next Tag: 10
 message ProcessStatsStateProto {
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8147b4a..2f3a491 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -51,6 +51,7 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
+    <protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" />
     <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
     <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
@@ -2268,6 +2269,11 @@
     <permission android:name="android.permission.START_ANY_ACTIVITY"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to start activities from background
+         @hide -->
+    <permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
+        android:protectionLevel="signature|privileged|vendorPrivileged|oem" />
+
     <!-- @SystemApi Must be required by activities that handle the intent action
          {@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
          hold {@link Manifest.permission#SUSPEND_APPS} to interact with the system.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1feb59a..d40f01c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -929,9 +929,6 @@
          in hardware. -->
     <bool name="config_setColorTransformAccelerated">false</bool>
 
-    <!-- Boolean indicating whether display white balance is supported. -->
-    <bool name="config_displayWhiteBalanceAvailable">false</bool>
-
     <!-- Control whether Night display is available. This should only be enabled on devices
          that have a HWC implementation that can apply the matrix passed to setColorTransform
          without impacting power, performance, and app compatibility (e.g. protected content). -->
@@ -987,6 +984,44 @@
         <!-- B y-intercept --> <item>-0.198650895</item>
     </string-array>
 
+    <!-- Boolean indicating whether display white balance is supported. -->
+    <bool name="config_displayWhiteBalanceAvailable">false</bool>
+
+    <!-- Minimum color temperature, in Kelvin, supported by display white balance. -->
+    <integer name="config_displayWhiteBalanceColorTemperatureMin">4000</integer>
+
+    <!-- Maximum color temperature, in Kelvin, supported by display white balance. -->
+    <integer name="config_displayWhiteBalanceColorTemperatureMax">8000</integer>
+
+    <!-- Default color temperature, in Kelvin, used by display white balance. -->
+    <integer name="config_displayWhiteBalanceColorTemperatureDefault">6500</integer>
+
+    <!-- The display primaries, in CIE1931 XYZ color space, for display
+         white balance to use in its calculations. -->
+    <string-array name="config_displayWhiteBalanceDisplayPrimaries">
+        <!-- Red X -->   <item>0.412315</item>
+        <!-- Red Y -->   <item>0.212600</item>
+        <!-- Red Z -->   <item>0.019327</item>
+        <!-- Green X --> <item>0.357600</item>
+        <!-- Green Y --> <item>0.715200</item>
+        <!-- Green Z --> <item>0.119200</item>
+        <!-- Blue X -->  <item>0.180500</item>
+        <!-- Blue Y -->  <item>0.072200</item>
+        <!-- Blue Z -->  <item>0.950633</item>
+        <!-- White X --> <item>0.950456</item>
+        <!-- White Y --> <item>1.000000</item>
+        <!-- White Z --> <item>1.089058</item>
+    </string-array>
+
+    <!-- The nominal white coordinates, in CIE1931 XYZ color space, for Display White Balance to
+         use in its calculations. AWB will adapt this white point to the target ambient white
+         point. -->
+    <string-array name="config_displayWhiteBalanceDisplayNominalWhite">
+        <!-- Nominal White X --> <item>0.950456</item>
+        <!-- Nominal White Y --> <item>1.000000</item>
+        <!-- Nominal White Z --> <item>1.089058</item>
+    </string-array>
+
 
     <!-- Indicate available ColorDisplayController.COLOR_MODE_xxx. -->
     <integer-array name="config_availableColorModes">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 010accf..a1ef0d5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3042,6 +3042,13 @@
   <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" />
   <java-symbol type="array" name="config_availableColorModes" />
 
+  <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
+  <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" />
+  <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMax" />
+  <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureDefault" />
+  <java-symbol type="array" name="config_displayWhiteBalanceDisplayPrimaries" />
+  <java-symbol type="array" name="config_displayWhiteBalanceDisplayNominalWhite" />
+
   <!-- Default first user restrictions -->
   <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 82eaf88..ec6101c 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -377,10 +377,10 @@
                         ConversationActions.Message.PERSON_USER_REMOTE)
                         .setText("Where are you?")
                         .build();
-        ConversationActions.TypeConfig typeConfig =
-                new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
+        TextClassifier.EntityConfig typeConfig =
+                new TextClassifier.EntityConfig.Builder().includeTypesFromTextClassifier(false)
                         .setIncludedTypes(
-                                Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+                                Collections.singletonList(ConversationAction.TYPE_TEXT_REPLY))
                         .build();
         ConversationActions.Request request =
                 new ConversationActions.Request.Builder(Collections.singletonList(message))
@@ -391,10 +391,10 @@
         ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
         assertTrue(conversationActions.getConversationActions().size() > 0);
         assertTrue(conversationActions.getConversationActions().size() == 1);
-        for (ConversationActions.ConversationAction conversationAction :
+        for (ConversationAction conversationAction :
                 conversationActions.getConversationActions()) {
             assertThat(conversationAction,
-                    isConversationAction(ConversationActions.TYPE_TEXT_REPLY));
+                    isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
         }
     }*/
 
@@ -406,10 +406,10 @@
                         ConversationActions.Message.PERSON_USER_REMOTE)
                         .setText("Where are you?")
                         .build();
-        ConversationActions.TypeConfig typeConfig =
-                new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
+        TextClassifier.EntityConfig typeConfig =
+                new TextClassifier.EntityConfig.Builder().includeTypesFromTextClassifier(false)
                         .setIncludedTypes(
-                                Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+                                Collections.singletonList(ConversationAction.TYPE_TEXT_REPLY))
                         .build();
         ConversationActions.Request request =
                 new ConversationActions.Request.Builder(Collections.singletonList(message))
@@ -418,10 +418,10 @@
 
         ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
         assertTrue(conversationActions.getConversationActions().size() > 1);
-        for (ConversationActions.ConversationAction conversationAction :
+        for (ConversationAction conversationAction :
                 conversationActions.getConversationActions()) {
             assertThat(conversationAction,
-                    isConversationAction(ConversationActions.TYPE_TEXT_REPLY));
+                    isConversationAction(ConversationAction.TYPE_TEXT_REPLY));
         }
     }
 
@@ -524,20 +524,19 @@
         };
     }
 
-    private static Matcher<ConversationActions.ConversationAction> isConversationAction(
-            String actionType) {
-        return new BaseMatcher<ConversationActions.ConversationAction>() {
+    private static Matcher<ConversationAction> isConversationAction(String actionType) {
+        return new BaseMatcher<ConversationAction>() {
             @Override
             public boolean matches(Object o) {
-                if (!(o instanceof ConversationActions.ConversationAction)) {
+                if (!(o instanceof ConversationAction)) {
                     return false;
                 }
-                ConversationActions.ConversationAction conversationAction =
-                        (ConversationActions.ConversationAction) o;
+                ConversationAction conversationAction =
+                        (ConversationAction) o;
                 if (!actionType.equals(conversationAction.getType())) {
                     return false;
                 }
-                if (ConversationActions.TYPE_TEXT_REPLY.equals(actionType)) {
+                if (ConversationAction.TYPE_TEXT_REPLY.equals(actionType)) {
                     if (conversationAction.getTextReply() == null) {
                         return false;
                     }
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 344f79d..0597a89 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -26,7 +26,7 @@
 import android.metrics.LogMaker;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.textclassifier.ConversationActions;
+import android.view.textclassifier.ConversationAction;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassifierEvent;
 import android.view.textclassifier.TextClassifierEventTronLogger;
@@ -69,7 +69,7 @@
                 new TextClassifierEvent.Builder(
                         TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS,
                         TextClassifierEvent.TYPE_SMART_ACTION)
-                        .setEntityType(ConversationActions.TYPE_CALL_PHONE)
+                        .setEntityType(ConversationAction.TYPE_CALL_PHONE)
                         .setEventTime(EVENT_TIME)
                         .setEventContext(textClassificationContext)
                         .build();
@@ -84,7 +84,7 @@
         assertThat(logMaker.getType()).isEqualTo(
                 ACTION_TEXT_SELECTION_SMART_SHARE);
         assertThat(logMaker.getTaggedData(FIELD_SELECTION_ENTITY_TYPE))
-                .isEqualTo(ConversationActions.TYPE_CALL_PHONE);
+                .isEqualTo(ConversationAction.TYPE_CALL_PHONE);
         assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME))
                 .isEqualTo(EVENT_TIME);
         assertThat(logMaker.getPackageName()).isEqualTo(PACKAGE_NAME);
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 0bffa38..6ce8148 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -41,7 +41,39 @@
     src: "privapp-permissions-platform.xml",
     required: [
         "privapp_whitelist_com.android.settings.intelligence",
-    ]
+    ],
+}
+
+prebuilt_etc {
+    name: "privapp_whitelist_com.android.carrierconfig",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.carrierconfig.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
+    name: "privapp_whitelist_com.android.contacts",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.contacts.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
+    name: "privapp_whitelist_com.android.launcher3",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.launcher3.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
+    name: "privapp_whitelist_com.android.provision",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.provision.xml",
+    filename_from_src: true,
 }
 
 prebuilt_etc {
@@ -60,6 +92,14 @@
 }
 
 prebuilt_etc {
+    name: "privapp_whitelist_com.android.storagemanager",
+    product_specific: true,
+    sub_dir: "permissions",
+    src: "com.android.storagemanager.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
     name: "privapp_whitelist_com.android.systemui",
     product_specific: true,
     sub_dir: "permissions",
diff --git a/data/etc/com.android.carrierconfig.xml b/data/etc/com.android.carrierconfig.xml
new file mode 100644
index 0000000..17efb03
--- /dev/null
+++ b/data/etc/com.android.carrierconfig.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.carrierconfig">
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.contacts.xml b/data/etc/com.android.contacts.xml
new file mode 100644
index 0000000..78eae40
--- /dev/null
+++ b/data/etc/com.android.contacts.xml
@@ -0,0 +1,22 @@
+<?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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.contacts">
+        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+        <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.launcher3.xml b/data/etc/com.android.launcher3.xml
new file mode 100644
index 0000000..337e153
--- /dev/null
+++ b/data/etc/com.android.launcher3.xml
@@ -0,0 +1,23 @@
+<?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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.launcher3">
+        <permission name="android.permission.BIND_APPWIDGET"/>
+        <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
+        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.provision.xml b/data/etc/com.android.provision.xml
new file mode 100644
index 0000000..05404ef
--- /dev/null
+++ b/data/etc/com.android.provision.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.provision">
+        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.storagemanager.xml b/data/etc/com.android.storagemanager.xml
new file mode 100644
index 0000000..e85a82c
--- /dev/null
+++ b/data/etc/com.android.storagemanager.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<permissions>
+    <privapp-permissions package="com.android.storagemanager">
+        <permission name="android.permission.DELETE_PACKAGES"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+        <permission name="android.permission.USE_RESERVED_DISK"/>
+        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index 221708b..3562a8f 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -44,6 +44,7 @@
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"/>
+        <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
         <permission name="android.permission.START_ACTIVITY_AS_CALLER"/>
         <permission name="android.permission.START_TASKS_FROM_RECENTS"/>
         <permission name="android.permission.STATUS_BAR"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 393a2a6..597d14a 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,10 +33,6 @@
         <permission name="android.permission.CRYPT_KEEPER"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.carrierconfig">
-        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.cellbroadcastreceiver">
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
@@ -45,11 +41,6 @@
         <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.contacts">
-        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
-        <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.defcontainer">
         <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
         <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
@@ -79,12 +70,6 @@
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.launcher3">
-        <permission name="android.permission.BIND_APPWIDGET"/>
-        <permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
-        <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.location.fused">
         <permission name="android.permission.INSTALL_LOCATION_PROVIDER"/>
     </privapp-permissions>
@@ -238,10 +223,6 @@
         <permission name="android.permission.USE_RESERVED_DISK"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.provision">
-        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.mainline.networkstack">
         <permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
         <permission name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"/>
@@ -335,6 +316,7 @@
         <permission name="android.permission.SET_TIME"/>
         <permission name="android.permission.SET_TIME_ZONE"/>
         <permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES"/>
+        <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
         <permission name="android.permission.START_TASKS_FROM_RECENTS" />
         <permission name="android.permission.STOP_APP_SWITCHES"/>
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
@@ -349,15 +331,6 @@
         <permission name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/>
     </privapp-permissions>
 
-    <privapp-permissions package="com.android.storagemanager">
-        <permission name="android.permission.DELETE_PACKAGES"/>
-        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
-        <permission name="android.permission.MANAGE_USERS"/>
-        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
-        <permission name="android.permission.USE_RESERVED_DISK"/>
-        <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
-    </privapp-permissions>
-
     <privapp-permissions package="com.android.tv">
         <permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
         <permission name="android.permission.DVB_DEVICE"/>
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index ca9dc47..65aaba1 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -22,6 +22,7 @@
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Canvas.VertexMode;
+import android.graphics.text.MeasuredText;
 import android.text.GraphicsOperations;
 import android.text.MeasuredParagraph;
 import android.text.PrecomputedText;
@@ -554,14 +555,12 @@
                     final int paraStart = pt.getParagraphStart(paraIndex);
                     final MeasuredParagraph mp = pt.getMeasuredParagraph(paraIndex);
                     // Only support the text in the same paragraph.
-                    nDrawTextRun(mNativeCanvasWrapper,
-                            mp.getChars(),
-                            start - paraStart,
-                            end - start,
-                            contextStart - paraStart,
-                            contextEnd - contextStart,
-                            x, y, isRtl, paint.getNativeInstance(),
-                            mp.getMeasuredText().getNativePtr());
+                    drawTextRun(mp.getMeasuredText(),
+                                start - paraStart,
+                                end - paraStart,
+                                contextStart - paraStart,
+                                contextEnd - paraStart,
+                                x, y, isRtl, paint);
                     return;
                 }
             }
@@ -576,6 +575,14 @@
         }
     }
 
+    public void drawTextRun(@NonNull MeasuredText measuredText, int start, int end,
+            int contextStart, int contextEnd, float x, float y, boolean isRtl,
+            @NonNull Paint paint) {
+        nDrawTextRun(mNativeCanvasWrapper, measuredText.getChars(), start, end - start,
+                contextStart, contextEnd - contextStart, x, y, isRtl, paint.getNativeInstance(),
+                measuredText.getNativePtr());
+    }
+
     public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
             int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
             int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index 901c211..4f60935 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.graphics.text.MeasuredText;
 import android.text.GraphicsOperations;
 import android.text.MeasuredParagraph;
 import android.text.PrecomputedText;
@@ -522,14 +523,12 @@
                     final int paraStart = pt.getParagraphStart(paraIndex);
                     final MeasuredParagraph mp = pt.getMeasuredParagraph(paraIndex);
                     // Only support if the target is in the same paragraph.
-                    nDrawTextRun(mNativeCanvasWrapper,
-                            mp.getChars(),
+                    drawTextRun(mp.getMeasuredText(),
                             start - paraStart,
-                            end - start,
+                            end - paraStart,
                             contextStart - paraStart,
-                            contextEnd - contextStart,
-                            x, y, isRtl, paint.getNativeInstance(),
-                            mp.getMeasuredText().getNativePtr());
+                            contextEnd - paraStart,
+                            x, y, isRtl, paint);
                     return;
                 }
             }
@@ -545,6 +544,15 @@
     }
 
     @Override
+    public void drawTextRun(@NonNull MeasuredText measuredText, int start, int end,
+            int contextStart, int contextEnd, float x, float y, boolean isRtl,
+            @NonNull Paint paint) {
+        nDrawTextRun(mNativeCanvasWrapper, measuredText.getChars(), start, end - start,
+                contextStart, contextEnd - contextStart, x, y, isRtl, paint.getNativeInstance(),
+                measuredText.getNativePtr());
+    }
+
+    @Override
     public final void drawVertices(@NonNull VertexMode mode, int vertexCount,
             @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset,
             @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 790b37e..30f0bfa 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -18,9 +18,11 @@
 
 import android.annotation.CheckResult;
 import android.annotation.ColorInt;
+import android.annotation.ColorLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.annotation.WorkerThread;
 import android.content.res.ResourcesImpl;
@@ -1780,6 +1782,30 @@
     }
 
     /**
+     * Fills the bitmap's pixels with the specified {@link Color}.
+     *
+     * @throws IllegalStateException if the bitmap is not mutable.
+     * @throws IllegalArgumentException if the color space encoded in the long
+     *                                  is invalid or unknown.
+     *
+     * @hide pending API approval
+     */
+    @TestApi
+    public void eraseColor(@ColorLong long c) {
+        checkRecycled("Can't erase a recycled bitmap");
+        if (!isMutable()) {
+            throw new IllegalStateException("cannot erase immutable bitmaps");
+        }
+
+        ColorSpace cs = Color.colorSpace(c);
+        float r = Color.red(c);
+        float g = Color.green(c);
+        float b = Color.blue(c);
+        float a = Color.alpha(c);
+        nativeErase(mNativePtr, cs, r, g, b, a);
+    }
+
+    /**
      * Returns the {@link Color} at the specified location. Throws an exception
      * if x or y are out of bounds (negative or >= to the width or height
      * respectively). The returned color is a non-premultiplied ARGB value in
@@ -2123,6 +2149,8 @@
                                             int quality, OutputStream stream,
                                             byte[] tempStorage);
     private static native void nativeErase(long nativeBitmap, int color);
+    private static native void nativeErase(long nativeBitmap, ColorSpace cs,
+                                           float r, float g, float b, float a);
     private static native int nativeRowBytes(long nativeBitmap);
     private static native int nativeConfig(long nativeBitmap);
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 63a806e..8c1bae2 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.text.MeasuredText;
 import android.os.Build;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -2122,7 +2123,8 @@
      * the text next to it.
      * <p>
      * All text outside the range {@code contextStart..contextEnd} is ignored. The text between
-     * {@code start} and {@code end} will be laid out and drawn.
+     * {@code start} and {@code end} will be laid out and drawn. The context range is useful for
+     * contextual shaping, e.g. Kerning, Arabic contextural form.
      * <p>
      * The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is
      * suitable only for runs of a single direction. Alignment of the text is as determined by the
@@ -2151,6 +2153,31 @@
     }
 
     /**
+     * Draw a run of text, all in a single direction, with optional context for complex text
+     * shaping.
+     * <p>
+     * See {@link #drawTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)} for
+     * more details. This method uses a {@link MeasuredText} rather than CharSequence to represent
+     * the string.
+     *
+     * @param text the text to render
+     * @param start the start of the text to render. Data before this position can be used for
+     *            shaping context.
+     * @param end the end of the text to render. Data at or after this position can be used for
+     *            shaping context.
+     * @param contextStart the index of the start of the shaping context
+     * @param contextEnd the index of the end of the shaping context
+     * @param x the x position at which to draw the text
+     * @param y the y position at which to draw the text
+     * @param isRtl whether the run is in RTL direction
+     * @param paint the paint
+     */
+    public void drawTextRun(@NonNull MeasuredText text, int start, int end, int contextStart,
+            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
+        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
+    }
+
+    /**
      * Draw the array of vertices, interpreted as triangles (based on mode). The verts array is
      * required, and specifies the x,y pairs for each vertex. If texs is non-null, then it is used
      * to specify the coordinate in shader coordinates to use at each vertex (the paint must have a
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 95317a4..9fa70a5 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1661,10 +1661,12 @@
      * @param rhs 3x3 matrix, as a non-null array of 9 floats
      * @return A new array of 9 floats containing the result of the multiplication
      *         of rhs by lhs
+     *
+     * @hide
      */
     @NonNull
     @Size(9)
-    private static float[] mul3x3(@NonNull @Size(9) float[] lhs, @NonNull @Size(9) float[] rhs) {
+    public static float[] mul3x3(@NonNull @Size(9) float[] lhs, @NonNull @Size(9) float[] rhs) {
         float[] r = new float[9];
         r[0] = lhs[0] * rhs[0] + lhs[3] * rhs[1] + lhs[6] * rhs[2];
         r[1] = lhs[1] * rhs[0] + lhs[4] * rhs[1] + lhs[7] * rhs[2];
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index ad9ec02..3c35d9b 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -20,8 +20,9 @@
 
 #include <algorithm>
 #include <iterator>
-#include <set>
 #include <map>
+#include <set>
+#include <sstream>
 
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
@@ -372,6 +373,9 @@
   uint32_t best_offset = 0u;
   uint32_t type_flags = 0u;
 
+  Resolution::Step::Type resolution_type;
+  std::vector<Resolution::Step> resolution_steps;
+
   // If desired_config is the same as the set configuration, then we can use our filtered list
   // and we don't need to match the configurations, since they already matched.
   const bool use_fast_path = desired_config == &configuration_;
@@ -403,8 +407,8 @@
     // If the package is an overlay, then even configurations that are the same MUST be chosen.
     const bool package_is_overlay = loaded_package->IsOverlay();
 
-    const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
     if (use_fast_path) {
+      const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
       const std::vector<ResTable_config>& candidate_configs = filtered_group.configurations;
       const size_t type_count = candidate_configs.size();
       for (uint32_t i = 0; i < type_count; i++) {
@@ -412,21 +416,34 @@
 
         // We can skip calling ResTable_config::match() because we know that all candidate
         // configurations that do NOT match have been filtered-out.
-        if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
-            (package_is_overlay && this_config.compare(*best_config) == 0)) {
-          // The configuration matches and is better than the previous selection.
-          // Find the entry value if it exists for this configuration.
-          const ResTable_type* type_chunk = filtered_group.types[i];
-          const uint32_t offset = LoadedPackage::GetEntryOffset(type_chunk, local_entry_idx);
-          if (offset == ResTable_type::NO_ENTRY) {
-            continue;
-          }
+        if (best_config == nullptr) {
+          resolution_type = Resolution::Step::Type::INITIAL;
+        } else if (this_config.isBetterThan(*best_config, desired_config)) {
+          resolution_type = Resolution::Step::Type::BETTER_MATCH;
+        } else if (package_is_overlay && this_config.compare(*best_config) == 0) {
+          resolution_type = Resolution::Step::Type::OVERLAID;
+        } else {
+          continue;
+        }
 
-          best_cookie = cookie;
-          best_package = loaded_package;
-          best_type = type_chunk;
-          best_config = &this_config;
-          best_offset = offset;
+        // The configuration matches and is better than the previous selection.
+        // Find the entry value if it exists for this configuration.
+        const ResTable_type* type = filtered_group.types[i];
+        const uint32_t offset = LoadedPackage::GetEntryOffset(type, local_entry_idx);
+        if (offset == ResTable_type::NO_ENTRY) {
+          continue;
+        }
+
+        best_cookie = cookie;
+        best_package = loaded_package;
+        best_type = type;
+        best_config = &this_config;
+        best_offset = offset;
+
+        if (resource_resolution_logging_enabled_) {
+          resolution_steps.push_back(Resolution::Step{resolution_type,
+                                                      this_config.toString(),
+                                                      &loaded_package->GetPackageName()});
         }
       }
     } else {
@@ -440,23 +457,38 @@
         ResTable_config this_config;
         this_config.copyFromDtoH((*iter)->config);
 
-        if (this_config.match(*desired_config)) {
-          if ((best_config == nullptr || this_config.isBetterThan(*best_config, desired_config)) ||
-              (package_is_overlay && this_config.compare(*best_config) == 0)) {
-            // The configuration matches and is better than the previous selection.
-            // Find the entry value if it exists for this configuration.
-            const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
-            if (offset == ResTable_type::NO_ENTRY) {
-              continue;
-            }
+        if (!this_config.match(*desired_config)) {
+          continue;
+        }
 
-            best_cookie = cookie;
-            best_package = loaded_package;
-            best_type = *iter;
-            best_config_copy = this_config;
-            best_config = &best_config_copy;
-            best_offset = offset;
-          }
+        if (best_config == nullptr) {
+          resolution_type = Resolution::Step::Type::INITIAL;
+        } else if (this_config.isBetterThan(*best_config, desired_config)) {
+          resolution_type = Resolution::Step::Type::BETTER_MATCH;
+        } else if (package_is_overlay && this_config.compare(*best_config) == 0) {
+          resolution_type = Resolution::Step::Type::OVERLAID;
+        } else {
+          continue;
+        }
+
+        // The configuration matches and is better than the previous selection.
+        // Find the entry value if it exists for this configuration.
+        const uint32_t offset = LoadedPackage::GetEntryOffset(*iter, local_entry_idx);
+        if (offset == ResTable_type::NO_ENTRY) {
+          continue;
+        }
+
+        best_cookie = cookie;
+        best_package = loaded_package;
+        best_type = *iter;
+        best_config_copy = this_config;
+        best_config = &best_config_copy;
+        best_offset = offset;
+
+        if (resource_resolution_logging_enabled_) {
+          resolution_steps.push_back(Resolution::Step{resolution_type,
+                                                      this_config.toString(),
+                                                      &loaded_package->GetPackageName()});
         }
       }
     }
@@ -478,9 +510,95 @@
   out_entry->entry_string_ref =
       StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
   out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
+
+  if (resource_resolution_logging_enabled_) {
+    last_resolution.resid = resid;
+    last_resolution.cookie = best_cookie;
+    last_resolution.steps = resolution_steps;
+
+    // Cache only the type/entry refs since that's all that's needed to build name
+    last_resolution.type_string_ref =
+        StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1);
+    last_resolution.entry_string_ref =
+        StringPoolRef(best_package->GetKeyStringPool(), best_entry->key.index);
+  }
+
   return best_cookie;
 }
 
+void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) {
+  resource_resolution_logging_enabled_ = enabled;
+
+  if (!enabled) {
+    last_resolution.cookie = kInvalidCookie;
+    last_resolution.resid = 0;
+    last_resolution.steps.clear();
+    last_resolution.type_string_ref = StringPoolRef();
+    last_resolution.entry_string_ref = StringPoolRef();
+  }
+}
+
+std::string AssetManager2::GetLastResourceResolution() const {
+  if (!resource_resolution_logging_enabled_) {
+    LOG(ERROR) << "Must enable resource resolution logging before getting path.";
+    return std::string();
+  }
+
+  auto cookie = last_resolution.cookie;
+  if (cookie == kInvalidCookie) {
+    LOG(ERROR) << "AssetManager hasn't resolved a resource to read resolution path.";
+    return std::string();
+  }
+
+  uint32_t resid = last_resolution.resid;
+  std::vector<Resolution::Step>& steps = last_resolution.steps;
+
+  ResourceName resource_name;
+  std::string resource_name_string;
+
+  const LoadedPackage* package =
+      apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+
+  if (package != nullptr) {
+    ToResourceName(last_resolution.type_string_ref,
+                   last_resolution.entry_string_ref,
+                   package,
+                   &resource_name);
+    resource_name_string = ToFormattedResourceString(&resource_name);
+  }
+
+  std::stringstream log_stream;
+  log_stream << base::StringPrintf("Resolution for 0x%08x ", resid)
+            << resource_name_string
+            << "\n\tFor config -"
+            << configuration_.toString();
+
+  std::string prefix;
+  for (Resolution::Step step : steps) {
+    switch (step.type) {
+      case Resolution::Step::Type::INITIAL:
+        prefix = "Found initial";
+        break;
+      case Resolution::Step::Type::BETTER_MATCH:
+        prefix = "Found better";
+        break;
+      case Resolution::Step::Type::OVERLAID:
+        prefix = "Overlaid";
+        break;
+    }
+
+    if (!prefix.empty()) {
+      log_stream << "\n\t" << prefix << ": " << *step.package_name;
+
+      if (!step.config_name.isEmpty()) {
+        log_stream << " -" << step.config_name;
+      }
+    }
+  }
+
+  return log_stream.str();
+}
+
 bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) const {
   FindEntryResult entry;
   ApkAssetsCookie cookie =
@@ -495,27 +613,10 @@
     return false;
   }
 
-  out_name->package = package->GetPackageName().data();
-  out_name->package_len = package->GetPackageName().size();
-
-  out_name->type = entry.type_string_ref.string8(&out_name->type_len);
-  out_name->type16 = nullptr;
-  if (out_name->type == nullptr) {
-    out_name->type16 = entry.type_string_ref.string16(&out_name->type_len);
-    if (out_name->type16 == nullptr) {
-      return false;
-    }
-  }
-
-  out_name->entry = entry.entry_string_ref.string8(&out_name->entry_len);
-  out_name->entry16 = nullptr;
-  if (out_name->entry == nullptr) {
-    out_name->entry16 = entry.entry_string_ref.string16(&out_name->entry_len);
-    if (out_name->entry16 == nullptr) {
-      return false;
-    }
-  }
-  return true;
+  return ToResourceName(entry.type_string_ref,
+                        entry.entry_string_ref,
+                        package,
+                        out_name);
 }
 
 bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) const {
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 57e3491..3dc1f2c 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -51,7 +51,7 @@
 class BagAttributeFinder
     : public BackTrackingAttributeFinder<BagAttributeFinder, const ResolvedBag::Entry*> {
  public:
-  BagAttributeFinder(const ResolvedBag* bag)
+  explicit BagAttributeFinder(const ResolvedBag* bag)
       : BackTrackingAttributeFinder(bag != nullptr ? bag->entries : nullptr,
                                     bag != nullptr ? bag->entries + bag->entry_count : nullptr) {
   }
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 5694115..a99e77f 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -94,7 +94,7 @@
         if (size < 0) {
             result = UNKNOWN_ERROR;
         } else {
-            int dupAshmemFd = ::dup(ashmemFd);
+            int dupAshmemFd = ::fcntl(ashmemFd, F_DUPFD_CLOEXEC, 0);
             if (dupAshmemFd < 0) {
                 result = -errno;
             } else {
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 5a26780..70ce9bc 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -593,7 +593,12 @@
           return {};
         }
 
-        // Iterate over the overlayable policy chunks
+        std::string name;
+        util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &name);
+        std::string actor;
+        util::ReadUtf16StringFromDevice(header->actor, arraysize(header->actor), &actor);
+
+        // Iterate over the overlayable policy chunks contained within the overlayable chunk data
         ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size());
         while (overlayable_iter.HasNext()) {
           const Chunk overlayable_child_chunk = overlayable_iter.Next();
@@ -613,7 +618,7 @@
                 return {};
               }
 
-              // Retrieve all the ids belonging to this policy
+              // Retrieve all the resource ids belonging to this policy chunk
               std::unordered_set<uint32_t> ids;
               const auto ids_begin =
                   reinterpret_cast<const ResTable_ref*>(overlayable_child_chunk.data_ptr());
@@ -622,8 +627,10 @@
                 ids.insert(dtohl(id_iter->ident));
               }
 
-              // Add the pairing of overlayable properties to resource ids to the package
+              // Add the pairing of overlayable properties and resource ids to the package
               OverlayableInfo overlayable_info{};
+              overlayable_info.name = name;
+              overlayable_info.actor = actor;
               overlayable_info.policy_flags = policy_header->policy_flags;
               loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids));
               break;
@@ -636,7 +643,7 @@
         }
 
         if (overlayable_iter.HadError()) {
-          LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_POLICY_TYPE: %s",
+          LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_TYPE: %s",
                                      overlayable_iter.GetLastError().c_str());
           if (overlayable_iter.HadFatalError()) {
             return {};
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
index d63feb01..645984d 100644
--- a/libs/androidfw/ResourceUtils.cpp
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -48,4 +48,65 @@
          !(has_type_separator && out_type->empty());
 }
 
+bool ToResourceName(StringPoolRef& type_string_ref,
+                    StringPoolRef& entry_string_ref,
+                    const LoadedPackage* package,
+                    AssetManager2::ResourceName* out_name) {
+  out_name->package = package->GetPackageName().data();
+  out_name->package_len = package->GetPackageName().size();
+
+  out_name->type = type_string_ref.string8(&out_name->type_len);
+  out_name->type16 = nullptr;
+  if (out_name->type == nullptr) {
+    out_name->type16 = type_string_ref.string16(&out_name->type_len);
+    if (out_name->type16 == nullptr) {
+      return false;
+    }
+  }
+
+  out_name->entry = entry_string_ref.string8(&out_name->entry_len);
+  out_name->entry16 = nullptr;
+  if (out_name->entry == nullptr) {
+    out_name->entry16 = entry_string_ref.string16(&out_name->entry_len);
+    if (out_name->entry16 == nullptr) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+std::string ToFormattedResourceString(AssetManager2::ResourceName* resource_name) {
+  std::string result;
+  if (resource_name->package != nullptr) {
+    result.append(resource_name->package, resource_name->package_len);
+  }
+
+  if (resource_name->type != nullptr || resource_name->type16 != nullptr) {
+    if (!result.empty()) {
+      result += ":";
+    }
+
+    if (resource_name->type != nullptr) {
+      result.append(resource_name->type, resource_name->type_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(resource_name->type16, resource_name->type_len));
+    }
+  }
+
+  if (resource_name->entry != nullptr || resource_name->entry16 != nullptr) {
+    if (!result.empty()) {
+      result += "/";
+    }
+
+    if (resource_name->entry != nullptr) {
+      result.append(resource_name->entry, resource_name->entry_len);
+    } else {
+      result += util::Utf16ToUtf8(StringPiece16(resource_name->entry16, resource_name->entry_len));
+    }
+  }
+
+  return result;
+}
+
 }  // namespace android
diff --git a/libs/androidfw/ZipUtils.cpp b/libs/androidfw/ZipUtils.cpp
index 5d243da..5be2105 100644
--- a/libs/androidfw/ZipUtils.cpp
+++ b/libs/androidfw/ZipUtils.cpp
@@ -37,7 +37,7 @@
 // TODO: This can go away once the only remaining usage in aapt goes away.
 class FileReader : public zip_archive::Reader {
   public:
-    FileReader(FILE* fp) : Reader(), mFp(fp), mCurrentOffset(0) {
+    explicit FileReader(FILE* fp) : Reader(), mFp(fp), mCurrentOffset(0) {
     }
 
     bool ReadAtOffset(uint8_t* buf, size_t len, uint32_t offset) const {
diff --git a/libs/androidfw/include/androidfw/AssetDir.h b/libs/androidfw/include/androidfw/AssetDir.h
index 7aef02d..ce6e066 100644
--- a/libs/androidfw/include/androidfw/AssetDir.h
+++ b/libs/androidfw/include/androidfw/AssetDir.h
@@ -78,7 +78,7 @@
     class FileInfo {
     public:
         FileInfo(void) {}
-        FileInfo(const String8& path)      // useful for e.g. svect.indexOf
+        explicit FileInfo(const String8& path)      // useful for e.g. svect.indexOf
             : mFileName(path), mFileType(kFileTypeUnknown)
             {}
         ~FileInfo(void) {}
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 0d49298..f29769b 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -229,6 +229,14 @@
                                    ResTable_config* in_out_selected_config, uint32_t* in_out_flags,
                                    uint32_t* out_last_reference) const;
 
+  // Enables or disables resource resolution logging. Clears stored steps when
+  // disabled.
+  void SetResourceResolutionLoggingEnabled(bool enabled);
+
+  // Returns formatted log of last resource resolution path, or empty if no
+  // resource has been resolved yet.
+  std::string GetLastResourceResolution() const;
+
   // Retrieves the best matching bag/map resource with ID `resid`.
   // This method will resolve all parent references for this bag and merge keys with the child.
   // To iterate over the keys, use the following idiom:
@@ -346,6 +354,48 @@
   // Cached set of bags. These are cached because they can inherit keys from parent bags,
   // which involves some calculation.
   std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
+
+  // Whether or not to save resource resolution steps
+  bool resource_resolution_logging_enabled_ = false;
+
+  struct Resolution {
+
+    struct Step {
+
+      enum class Type {
+        INITIAL,
+        BETTER_MATCH,
+        OVERLAID
+      };
+
+      // Marks what kind of override this step was.
+      Type type;
+
+      // Built name of configuration for this step.
+      String8 config_name;
+
+      // Marks the package name of the better resource found in this step.
+      const std::string* package_name;
+    };
+
+    // Last resolved resource ID.
+    uint32_t resid;
+
+    // Last resolved resource result cookie.
+    ApkAssetsCookie cookie = kInvalidCookie;
+
+    // Last resolved resource type.
+    StringPoolRef type_string_ref;
+
+    // Last resolved resource entry.
+    StringPoolRef entry_string_ref;
+
+    // Steps taken to resolve last resource.
+    std::vector<Step> steps;
+  };
+
+  // Record of the last resolved resource's resolution path.
+  mutable Resolution last_resolution;
 };
 
 class Theme {
diff --git a/libs/androidfw/include/androidfw/BackupHelpers.h b/libs/androidfw/include/androidfw/BackupHelpers.h
index fc1ad47..2da247b 100644
--- a/libs/androidfw/include/androidfw/BackupHelpers.h
+++ b/libs/androidfw/include/androidfw/BackupHelpers.h
@@ -67,7 +67,7 @@
 class BackupDataWriter
 {
 public:
-    BackupDataWriter(int fd);
+    explicit BackupDataWriter(int fd);
     // does not close fd
     ~BackupDataWriter();
 
@@ -104,7 +104,7 @@
 class BackupDataReader
 {
 public:
-    BackupDataReader(int fd);
+    explicit BackupDataReader(int fd);
     // does not close fd
     ~BackupDataReader();
 
diff --git a/libs/androidfw/include/androidfw/ConfigDescription.h b/libs/androidfw/include/androidfw/ConfigDescription.h
index 29424c4..6fa089a 100644
--- a/libs/androidfw/include/androidfw/ConfigDescription.h
+++ b/libs/androidfw/include/androidfw/ConfigDescription.h
@@ -82,7 +82,7 @@
   static void ApplyVersionForCompatibility(ConfigDescription* config);
 
   ConfigDescription();
-  ConfigDescription(const android::ResTable_config& o);  // NOLINT(implicit)
+  ConfigDescription(const android::ResTable_config& o);  // NOLINT(google-explicit-constructor)
   ConfigDescription(const ConfigDescription& o);
   ConfigDescription(ConfigDescription&& o) noexcept;
 
diff --git a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
index e1dfb94..bf35aa3 100644
--- a/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
+++ b/libs/androidfw/include/androidfw/DisplayEventDispatcher.h
@@ -22,7 +22,7 @@
 
 class DisplayEventDispatcher : public LooperCallback {
 public:
-    DisplayEventDispatcher(const sp<Looper>& looper,
+    explicit DisplayEventDispatcher(const sp<Looper>& looper,
             ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
 
     status_t initialize();
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 8c5c3b7..be62f30 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -78,6 +78,8 @@
 using TypeSpecPtr = util::unique_cptr<TypeSpec>;
 
 struct OverlayableInfo {
+  std::string name;
+  std::string actor;
   uint32_t policy_flags;
 };
 
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index cf2d8fb..6b9ebd3 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -693,7 +693,7 @@
 class ResXMLParser
 {
 public:
-    ResXMLParser(const ResXMLTree& tree);
+    explicit ResXMLParser(const ResXMLTree& tree);
 
     enum event_code_t {
         BAD_DOCUMENT = -1,
@@ -806,7 +806,7 @@
      * The tree stores a clone of the specified DynamicRefTable, so any changes to the original
      * DynamicRefTable will not affect this tree after instantiation.
      **/
-    ResXMLTree(const DynamicRefTable* dynamicRefTable);
+    explicit ResXMLTree(const DynamicRefTable* dynamicRefTable);
     ResXMLTree();
     ~ResXMLTree();
 
@@ -1611,6 +1611,12 @@
 struct ResTable_overlayable_header
 {
   struct ResChunk_header header;
+
+  // The name of the overlayable set of resources that overlays target.
+  uint16_t name[256];
+
+ // The component responsible for enabling and disabling overlays targeting this chunk.
+  uint16_t actor[256];
 };
 
 /**
@@ -1844,7 +1850,7 @@
 
     class Theme {
     public:
-        Theme(const ResTable& table);
+        explicit Theme(const ResTable& table);
         ~Theme();
 
         inline const ResTable& getResTable() const { return mTable; }
diff --git a/libs/androidfw/include/androidfw/ResourceUtils.h b/libs/androidfw/include/androidfw/ResourceUtils.h
index d94779b..eb6eb8e 100644
--- a/libs/androidfw/include/androidfw/ResourceUtils.h
+++ b/libs/androidfw/include/androidfw/ResourceUtils.h
@@ -17,6 +17,7 @@
 #ifndef ANDROIDFW_RESOURCEUTILS_H
 #define ANDROIDFW_RESOURCEUTILS_H
 
+#include "androidfw/AssetManager2.h"
 #include "androidfw/StringPiece.h"
 
 namespace android {
@@ -27,6 +28,17 @@
 bool ExtractResourceName(const StringPiece& str, StringPiece* out_package, StringPiece* out_type,
                          StringPiece* out_entry);
 
+// Convert a type_string_ref, entry_string_ref, and package
+// to AssetManager2::ResourceName. Useful for getting
+// resource name without re-running AssetManager2::FindEntry searches.
+bool ToResourceName(StringPoolRef& type_string_ref,
+                    StringPoolRef& entry_string_ref,
+                    const LoadedPackage* package,
+                    AssetManager2::ResourceName* out_name);
+
+// Formats a ResourceName to "package:type/entry_name".
+std::string ToFormattedResourceString(AssetManager2::ResourceName* resource_name);
+
 inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
   return (resid & 0x00ffffffu) | (static_cast<uint32_t>(package_id) << 24);
 }
diff --git a/libs/androidfw/include/androidfw/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h
index a33865f..921877dc 100644
--- a/libs/androidfw/include/androidfw/StringPiece.h
+++ b/libs/androidfw/include/androidfw/StringPiece.h
@@ -52,8 +52,8 @@
 
   BasicStringPiece();
   BasicStringPiece(const BasicStringPiece<TChar>& str);
-  BasicStringPiece(const std::basic_string<TChar>& str);  // NOLINT(implicit)
-  BasicStringPiece(const TChar* str);                     // NOLINT(implicit)
+  BasicStringPiece(const std::basic_string<TChar>& str);  // NOLINT(google-explicit-constructor)
+  BasicStringPiece(const TChar* str);                     // NOLINT(google-explicit-constructor)
   BasicStringPiece(const TChar* str, size_t len);
 
   BasicStringPiece<TChar>& operator=(const BasicStringPiece<TChar>& rhs);
diff --git a/libs/androidfw/include/androidfw/TypeWrappers.h b/libs/androidfw/include/androidfw/TypeWrappers.h
index 5cfe54e5..fb2fad6 100644
--- a/libs/androidfw/include/androidfw/TypeWrappers.h
+++ b/libs/androidfw/include/androidfw/TypeWrappers.h
@@ -23,7 +23,7 @@
 namespace android {
 
 struct TypeVariant {
-    TypeVariant(const ResTable_type* data);
+    explicit TypeVariant(const ResTable_type* data);
 
     class iterator {
     public:
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 10d088e..aa1466f 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -46,7 +46,7 @@
   using pointer = typename std::add_pointer<T>::type;
 
   constexpr unique_cptr() : ptr_(nullptr) {}
-  constexpr unique_cptr(std::nullptr_t) : ptr_(nullptr) {}
+  constexpr explicit unique_cptr(std::nullptr_t) : ptr_(nullptr) {}
   explicit unique_cptr(pointer ptr) : ptr_(ptr) {}
   unique_cptr(unique_cptr&& o) noexcept : ptr_(o.ptr_) { o.ptr_ = nullptr; }
 
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 5449a54..105dcd2 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -586,4 +586,111 @@
   EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory));
 }
 
+TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) {
+  ResTable_config desired_config;
+
+  AssetManager2 assetmanager;
+  assetmanager.SetConfiguration(desired_config);
+  assetmanager.SetApkAssets({basic_assets_.get()});
+  assetmanager.SetResourceResolutionLoggingEnabled(false);
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
+                               0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  auto result = assetmanager.GetLastResourceResolution();
+  EXPECT_EQ("", result);
+}
+
+TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) {
+  ResTable_config desired_config;
+
+  AssetManager2 assetmanager;
+  assetmanager.SetConfiguration(desired_config);
+  assetmanager.SetApkAssets({basic_assets_.get()});
+
+  auto result = assetmanager.GetLastResourceResolution();
+  EXPECT_EQ("", result);
+}
+
+TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) {
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
+  desired_config.language[0] = 'd';
+  desired_config.language[1] = 'e';
+
+  AssetManager2 assetmanager;
+  assetmanager.SetResourceResolutionLoggingEnabled(true);
+  assetmanager.SetConfiguration(desired_config);
+  assetmanager.SetApkAssets({basic_assets_.get()});
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
+                               0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  auto result = assetmanager.GetLastResourceResolution();
+  EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n\tFor config -de\n\tFound initial: com.android.basic", result);
+}
+
+TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) {
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
+  desired_config.language[0] = 'd';
+  desired_config.language[1] = 'e';
+
+  AssetManager2 assetmanager;
+  assetmanager.SetResourceResolutionLoggingEnabled(true);
+  assetmanager.SetConfiguration(desired_config);
+  assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()});
+
+  Res_value value = Res_value();
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
+                               0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  auto result = assetmanager.GetLastResourceResolution();
+  EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n\tFor config -de\n\tFound initial: com.android.basic\n\tFound better: com.android.basic -de", result);
+}
+
+TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) {
+  ResTable_config desired_config;
+  memset(&desired_config, 0, sizeof(desired_config));
+
+  AssetManager2 assetmanager;
+  assetmanager.SetResourceResolutionLoggingEnabled(true);
+  assetmanager.SetConfiguration(desired_config);
+  assetmanager.SetApkAssets({basic_assets_.get()});
+
+  Res_value value = Res_value();
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
+                               0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  auto resultEnabled = assetmanager.GetLastResourceResolution();
+  ASSERT_NE("", resultEnabled);
+
+  assetmanager.SetResourceResolutionLoggingEnabled(false);
+
+  auto resultDisabled = assetmanager.GetLastResourceResolution();
+  EXPECT_EQ("", resultDisabled);
+}
+
 }  // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 22d587a..2e386a0 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -294,22 +294,30 @@
 
   info = package->GetOverlayableInfo(overlayable::R::string::overlayable1);
   ASSERT_THAT(info, NotNull());
+  EXPECT_THAT(info->name, Eq("OverlayableResources1"));
+  EXPECT_THAT(info->actor, Eq("overlay://theme"));
   EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC));
 
   info = package->GetOverlayableInfo(overlayable::R::string::overlayable2);
   ASSERT_THAT(info, NotNull());
+  EXPECT_THAT(info->name, Eq("OverlayableResources1"));
+  EXPECT_THAT(info->actor, Eq("overlay://theme"));
   EXPECT_THAT(info->policy_flags,
               Eq(ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION
                  | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION));
 
   info = package->GetOverlayableInfo(overlayable::R::string::overlayable3);
   ASSERT_THAT(info, NotNull());
+  EXPECT_THAT(info->name, Eq("OverlayableResources2"));
+  EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable"));
   EXPECT_THAT(info->policy_flags,
               Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION
                  | ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION
                  | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION));
 
   info = package->GetOverlayableInfo(overlayable::R::string::overlayable4);
+  EXPECT_THAT(info->name, Eq("OverlayableResources1"));
+  EXPECT_THAT(info->actor, Eq("overlay://theme"));
   ASSERT_THAT(info, NotNull());
   EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC));
 }
diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk
index 85ab4be..8634747 100644
--- a/libs/androidfw/tests/data/overlayable/overlayable.apk
+++ b/libs/androidfw/tests/data/overlayable/overlayable.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
index 11aa735..dba7b08 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
@@ -15,7 +15,7 @@
 -->
 
 <resources>
-<overlayable>
+<overlayable name="OverlayableResources1" actor="overlay://theme">
     <!-- Any overlay can overlay the value of @string/overlayable1 -->
     <item type="string" name="overlayable1" />
 
@@ -31,9 +31,9 @@
     </policy>
 </overlayable>
 
-<overlayable>
+<overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
     <!-- Any overlay on the product_services, vendor, or product partition can overlay the value of
-   @string/overlayable3 -->
+        @string/overlayable3 -->
     <policy type="product_services|vendor|product">
         <item type="string" name="overlayable3" />
     </policy>
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index ed167e5..56b1885 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -79,8 +79,7 @@
     switch (wcgDataspace) {
         case ui::Dataspace::DISPLAY_P3:
             *colorGamut = SkColorSpace::Gamut::kDCIP3_D65_Gamut;
-            *colorSpace = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                                SkColorSpace::Gamut::kDCIP3_D65_Gamut);
+            *colorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3);
             break;
         case ui::Dataspace::V0_SCRGB:
             *colorGamut = SkColorSpace::Gamut::kSRGB_Gamut;
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index b2351fc..fd824bd 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -52,17 +52,8 @@
     // Input: Format of the destination surface.
     VkFormat format;
 
-    // Input: Color space transfer params
-    float g;
-    float a;
-    float b;
-    float c;
-    float d;
-    float e;
-    float f;
-
-    // Input: Color space transformation from linear RGB to D50-adapted XYZ
-    float colorSpaceTransform[9];
+    // Input: Color space
+    const SkColorSpace* colorSpaceInfo;
 
     // Input: current clip rect
     int clipLeft;
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index f3a7648..f6178af 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -44,8 +44,8 @@
 }
 
 TEST(SkiaCanvas, colorSpaceXform) {
-    sk_sp<SkColorSpace> adobe = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
-                                                      SkColorSpace::kAdobeRGB_Gamut);
+    sk_sp<SkColorSpace> adobe = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
+                                                      SkNamedGamut::kAdobeRGB);
 
     SkImageInfo adobeInfo = SkImageInfo::Make(1, 1, kN32_SkColorType, kOpaque_SkAlphaType, adobe);
     sk_sp<Bitmap> adobeBitmap = Bitmap::allocateHeapBitmap(adobeInfo);
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index dc347f6..4415a59 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -25,38 +25,6 @@
 namespace android {
 namespace uirenderer {
 
-static inline bool almostEqual(float a, float b) {
-    return std::abs(a - b) < 1e-2f;
-}
-
-bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace) {
-    if (colorSpace == nullptr) return true;
-    if (colorSpace->isSRGB()) return true;
-
-    SkColorSpaceTransferFn transferFunction;
-    if (colorSpace->isNumericalTransferFn(&transferFunction)) {
-        // sRGB transfer function params:
-        const float sRGBParamA = 1 / 1.055f;
-        const float sRGBParamB = 0.055f / 1.055f;
-        const float sRGBParamC = 1 / 12.92f;
-        const float sRGBParamD = 0.04045f;
-        const float sRGBParamE = 0.0f;
-        const float sRGBParamF = 0.0f;
-        const float sRGBParamG = 2.4f;
-
-        // This comparison will catch Display P3
-        return almostEqual(sRGBParamA, transferFunction.fA) &&
-               almostEqual(sRGBParamB, transferFunction.fB) &&
-               almostEqual(sRGBParamC, transferFunction.fC) &&
-               almostEqual(sRGBParamD, transferFunction.fD) &&
-               almostEqual(sRGBParamE, transferFunction.fE) &&
-               almostEqual(sRGBParamF, transferFunction.fF) &&
-               almostEqual(sRGBParamG, transferFunction.fG);
-    }
-
-    return false;
-}
-
 android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType) {
     switch (colorType) {
         case kRGBA_8888_SkColorType:
@@ -79,19 +47,19 @@
 
 sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) {
 
-    SkColorSpace::Gamut gamut;
+    skcms_Matrix3x3 gamut;
     switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
         case HAL_DATASPACE_STANDARD_BT709:
-            gamut = SkColorSpace::kSRGB_Gamut;
+            gamut = SkNamedGamut::kSRGB;
             break;
         case HAL_DATASPACE_STANDARD_BT2020:
-            gamut = SkColorSpace::kRec2020_Gamut;
+            gamut = SkNamedGamut::kRec2020;
             break;
         case HAL_DATASPACE_STANDARD_DCI_P3:
-            gamut = SkColorSpace::kDCIP3_D65_Gamut;
+            gamut = SkNamedGamut::kDCIP3;
             break;
         case HAL_DATASPACE_STANDARD_ADOBE_RGB:
-            gamut = SkColorSpace::kAdobeRGB_Gamut;
+            gamut = SkNamedGamut::kAdobeRGB;
             break;
         case HAL_DATASPACE_STANDARD_UNSPECIFIED:
             return nullptr;
@@ -109,9 +77,9 @@
 
     switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
         case HAL_DATASPACE_TRANSFER_LINEAR:
-            return SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, gamut);
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
         case HAL_DATASPACE_TRANSFER_SRGB:
-            return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, gamut);
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
         case HAL_DATASPACE_TRANSFER_GAMMA2_2:
             return SkColorSpace::MakeRGB({2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, gamut);
         case HAL_DATASPACE_TRANSFER_GAMMA2_6:
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 4473ce6..3880252 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -111,11 +111,6 @@
 #endif
 }
 
-// Returns whether the specified color space's transfer function can be
-// approximated with the native sRGB transfer function. This method
-// returns true for sRGB, gamma 2.2 and Display P3 for instance
-bool transferFunctionCloseToSRGB(const SkColorSpace* colorSpace);
-
 android::PixelFormat ColorTypeToPixelFormat(SkColorType colorType);
 
 ANDROID_API sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace);
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index f179bc3..602cc3e 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -48,6 +48,7 @@
     private int mMultipathIndicator;
     private double mSnrInDb;
     private double mAutomaticGainControlLevelInDb;
+    private int mCodeType;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -58,6 +59,7 @@
     private static final int HAS_CARRIER_PHASE = (1<<11);
     private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
     private static final int HAS_AUTOMATIC_GAIN_CONTROL = (1<<13);
+    private static final int HAS_CODE_TYPE = (1 << 14);
 
     /**
      * The status of the multipath indicator.
@@ -202,6 +204,104 @@
     public static final int ADR_STATE_HALF_CYCLE_REPORTED = (1<<4);
 
     /**
+     * GNSS measurement code type.
+     * @hide
+     */
+    @IntDef(prefix = { "CODE_TYPE_" }, value = {
+            CODE_TYPE_UNKNOWN, CODE_TYPE_A, CODE_TYPE_B, CODE_TYPE_C, CODE_TYPE_I, CODE_TYPE_L,
+            CODE_TYPE_M, CODE_TYPE_P, CODE_TYPE_Q, CODE_TYPE_S, CODE_TYPE_W, CODE_TYPE_X,
+            CODE_TYPE_Y, CODE_TYPE_Z, CODE_TYPE_CODELESS
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CodeType {}
+
+    /** The GNSS Measurement's code type is unknown. */
+    public static final int CODE_TYPE_UNKNOWN = -1;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GALILEO E1A, GALILEO E6A, IRNSS
+     * L5A, IRNSS SA.
+     */
+    public static final int CODE_TYPE_A = 0;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GALILEO E1B, GALILEO E6B, IRNSS
+     * L5B, IRNSS SB.
+     */
+    public static final int CODE_TYPE_B = 1;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1 C/A,  GPS L2 C/A, GLONASS G1
+     * C/A, GLONASS G2 C/A, GALILEO E1C, GALILEO E6C, SBAS L1 C/A, QZSS L1 C/A, IRNSS L5C.
+     */
+    public static final int CODE_TYPE_C = 2;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L5 I, GLONASS G3 I, GALILEO E5a
+     * I, GALILEO E5b I, GALILEO E5a+b I, SBAS L5 I, QZSS L5 I, BDS B1 I, BDS B2 I, BDS B3 I.
+     */
+    public static final int CODE_TYPE_I = 3;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1C (P), GPS L2C (L), QZSS L1C
+     * (P), QZSS L2C (L), LEX(6) L.
+     */
+    public static final int CODE_TYPE_L = 4;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1M, GPS L2M.
+     */
+    public static final int CODE_TYPE_M = 5;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1P, GPS L2P, GLONASS G1P,
+     * GLONASS G2P.
+     */
+    public static final int CODE_TYPE_P = 6;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L5 Q, GLONASS G3 Q, GALILEO E5a
+     * Q, GALILEO E5b Q, GALILEO E5a+b Q, SBAS L5 Q, QZSS L5 Q, BDS B1 Q, BDS B2 Q, BDS B3 Q.
+     */
+    public static final int CODE_TYPE_Q = 7;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1C (D), GPS L2C (M), QZSS L1C
+     * (D), QZSS L2C (M), LEX(6) S.
+     */
+    public static final int CODE_TYPE_S = 8;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1 Z-tracking, GPS L2
+     * Z-tracking.
+     */
+    public static final int CODE_TYPE_W = 9;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1C (D+P), GPS L2C (M+L), GPS
+     * L5 (I+Q), GLONASS G3 (I+Q), GALILEO E1 (B+C), GALILEO E5a (I+Q), GALILEO E5b (I+Q), GALILEO
+     * E5a+b(I+Q), GALILEO E6 (B+C), SBAS L5 (I+Q), QZSS L1C (D+P), QZSS L2C (M+L), QZSS L5 (I+Q),
+     * LEX(6) (S+L), BDS B1 (I+Q), BDS B2 (I+Q), BDS B3 (I+Q), IRNSS L5 (B+C).
+     */
+    public static final int CODE_TYPE_X = 10;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1Y, GPS L2Y.
+     */
+    public static final int CODE_TYPE_Y = 11;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GALILEO E1 (A+B+C), GALILEO E6
+     * (A+B+C), QZSS L1-SAIF.
+     */
+    public static final int CODE_TYPE_Z = 12;
+
+    /**
+     * The GNSS Measurement's code type is one of the following: GPS L1 codeless, GPS L2 codeless.
+     */
+    public static final int CODE_TYPE_CODELESS = 13;
+
+    /**
      * All the 'Accumulated Delta Range' flags.
      * @hide
      */
@@ -248,6 +348,7 @@
         mMultipathIndicator = measurement.mMultipathIndicator;
         mSnrInDb = measurement.mSnrInDb;
         mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb;
+        mCodeType = measurement.mCodeType;
     }
 
     /**
@@ -967,7 +1068,7 @@
      * <p>For internal and logging use only.
      */
     private String getMultipathIndicatorString() {
-        switch(mMultipathIndicator) {
+        switch (mMultipathIndicator) {
             case MULTIPATH_INDICATOR_UNKNOWN:
                 return "Unknown";
             case MULTIPATH_INDICATOR_DETECTED:
@@ -1063,6 +1164,89 @@
         mAutomaticGainControlLevelInDb = Double.NaN;
     }
 
+    /**
+     * Returns {@code true} if {@link #getCodeType()} is available,
+     * {@code false} otherwise.
+     */
+    public boolean hasCodeType() {
+        return isFlagSet(HAS_CODE_TYPE);
+    }
+
+    /**
+     * Gets the GNSS measurement's code type.
+     *
+     * <p>Similar to the Attribute field described in Rinex 3.03, e.g., in Tables 4-10, and Table
+     * A2 at the Rinex 3.03 Update 1 Document.
+     */
+    @CodeType
+    public int getCodeType() {
+        return mCodeType;
+    }
+
+    /**
+     * Sets the GNSS measurement's code type.
+     *
+     * @hide
+     */
+    @TestApi
+    public void setCodeType(@CodeType int codeType) {
+        setFlag(HAS_CODE_TYPE);
+        mCodeType = codeType;
+    }
+
+    /**
+     * Resets the GNSS measurement's code type.
+     *
+     * @hide
+     */
+    @TestApi
+    public void resetCodeType() {
+        resetFlag(HAS_CODE_TYPE);
+        mCodeType = CODE_TYPE_UNKNOWN;
+    }
+
+    /**
+     * Gets a string representation of the 'code type'.
+     *
+     * <p>For internal and logging use only.
+     */
+    private String getCodeTypeString() {
+        switch (mCodeType) {
+            case CODE_TYPE_UNKNOWN:
+                return "CODE_TYPE_UNKNOWN";
+            case CODE_TYPE_A:
+                return "CODE_TYPE_A";
+            case CODE_TYPE_B:
+                return "CODE_TYPE_B";
+            case CODE_TYPE_C:
+                return "CODE_TYPE_C";
+            case CODE_TYPE_I:
+                return "CODE_TYPE_I";
+            case CODE_TYPE_L:
+                return "CODE_TYPE_L";
+            case CODE_TYPE_M:
+                return "CODE_TYPE_M";
+            case CODE_TYPE_P:
+                return "CODE_TYPE_P";
+            case CODE_TYPE_Q:
+                return "CODE_TYPE_Q";
+            case CODE_TYPE_S:
+                return "CODE_TYPE_S";
+            case CODE_TYPE_W:
+                return "CODE_TYPE_W";
+            case CODE_TYPE_X:
+                return "CODE_TYPE_X";
+            case CODE_TYPE_Y:
+                return "CODE_TYPE_Y";
+            case CODE_TYPE_Z:
+                return "CODE_TYPE_Z";
+            case CODE_TYPE_CODELESS:
+                return "CODE_TYPE_CODELESS";
+            default:
+                return "<Invalid: " + mCodeType + ">";
+        }
+    }
+
     public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
         @Override
         public GnssMeasurement createFromParcel(Parcel parcel) {
@@ -1088,6 +1272,7 @@
             gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
             gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble();
+            gnssMeasurement.mCodeType = parcel.readInt();
 
             return gnssMeasurement;
         }
@@ -1120,6 +1305,7 @@
         parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
         parcel.writeDouble(mAutomaticGainControlLevelInDb);
+        parcel.writeInt(mCodeType);
     }
 
     @Override
@@ -1191,9 +1377,13 @@
                 "SnrInDb",
                 hasSnrInDb() ? mSnrInDb : null));
         builder.append(String.format(
-            format,
-            "AgcLevelDb",
-            hasAutomaticGainControlLevelDb() ? mAutomaticGainControlLevelInDb : null));
+                format,
+                "AgcLevelDb",
+                hasAutomaticGainControlLevelDb() ? mAutomaticGainControlLevelInDb : null));
+        builder.append(String.format(
+                format,
+                "CodeType",
+                hasCodeType() ? getCodeTypeString() : null));
 
         return builder.toString();
     }
@@ -1218,6 +1408,7 @@
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
         resetAutomaticGainControlLevel();
+        resetCodeType();
     }
 
     private void setFlag(int flag) {
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 0375de3..bc9500d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2289,6 +2289,30 @@
          */
         public static final int ERROR_UNSUPPORTED_OPERATION = 6;
 
+        /**
+         * This indicates that the security level of the device is not
+         * sufficient to meet the requirements set by the content owner
+         * in the license policy.
+         */
+        public static final int ERROR_INSUFFICIENT_SECURITY = 7;
+
+        /**
+         * This indicates that the video frame being decrypted exceeds
+         * the size of the device's protected output buffers. When
+         * encountering this error the app should try playing content
+         * of a lower resolution.
+         */
+        public static final int ERROR_FRAME_TOO_LARGE = 8;
+
+        /**
+         * This error indicates that session state has been
+         * invalidated. It can occur on devices that are not capable
+         * of retaining crypto session state across device
+         * suspend/resume. The session must be closed and a new
+         * session opened to resume operation.
+         */
+        public static final int ERROR_LOST_STATE = 9;
+
         /** @hide */
         @IntDef({
             ERROR_NO_KEY,
@@ -2296,7 +2320,10 @@
             ERROR_RESOURCE_BUSY,
             ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
             ERROR_SESSION_NOT_OPENED,
-            ERROR_UNSUPPORTED_OPERATION
+            ERROR_UNSUPPORTED_OPERATION,
+            ERROR_INSUFFICIENT_SECURITY,
+            ERROR_FRAME_TOO_LARGE,
+            ERROR_LOST_STATE
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface CryptoErrorCode {}
diff --git a/media/java/android/media/MediaConstants.java b/media/java/android/media/MediaConstants.java
index 275b0ac..5a5747a 100644
--- a/media/java/android/media/MediaConstants.java
+++ b/media/java/android/media/MediaConstants.java
@@ -24,7 +24,7 @@
     static final String KEY_PACKAGE_NAME = "android.media.key.PACKAGE_NAME";
 
     // Bundle key for Parcelable
-    static final String KEY_SESSION2_STUB = "android.media.key.SESSION2_STUB";
+    static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK";
     static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS";
 
     private MediaConstants() {
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index b8381a7..774ea18 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -19,7 +19,7 @@
 import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
 import static android.media.MediaConstants.KEY_PACKAGE_NAME;
 import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_SESSION2_STUB;
+import static android.media.MediaConstants.KEY_SESSION2LINK;
 import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
 import static android.media.Session2Command.RESULT_INFO_SKIPPED;
 import static android.media.Session2Token.TYPE_SESSION;
@@ -41,15 +41,15 @@
 
 /**
  * Allows an app to interact with an active {@link MediaSession2} or a
- * {@link MediaSession2Service} which would provide {@link MediaSession2}. Media buttons and other
+ * MediaSession2Service which would provide {@link MediaSession2}. Media buttons and other
  * commands can be sent to the session.
  * <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.
- * @hide
  */
+// TODO: use @link for MediaSession2Service
 public class MediaController2 implements AutoCloseable {
     static final String TAG = "MediaController2";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -130,8 +130,8 @@
         synchronized (mLock) {
             if (mSessionBinder != null) {
                 try {
-                    mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
                     mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
+                    mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
                 } catch (RuntimeException e) {
                     // No-op
                 }
@@ -153,6 +153,7 @@
      * @return a token which will be sent together in {@link ControllerCallback#onCommandResult}
      *        when its result is received.
      */
+    @NonNull
     public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
         if (command == null) {
             throw new IllegalArgumentException("command shouldn't be null");
@@ -208,7 +209,7 @@
     void onConnected(int seq, Bundle connectionResult) {
         final long token = Binder.clearCallingIdentity();
         try {
-            Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2_STUB);
+            Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
             Session2CommandGroup allowedCommands =
                     connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
             if (DEBUG) {
@@ -349,7 +350,7 @@
          * @return the result for the session command. A runtime exception will be thrown if null
          *         is returned.
          */
-        @NonNull
+        @Nullable
         public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller,
                 @NonNull Session2Command command, @Nullable Bundle args) {
             return null;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index cdbc7b44..75b3915 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -132,11 +132,19 @@
     private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
 
     private EventHandler mEventHandler;
-    private EventHandler mOnKeyStatusChangeEventHandler;
-    private EventHandler mOnExpirationUpdateEventHandler;
+    private EventHandler mKeyStatusChangeHandler;
+    private EventHandler mExpirationUpdateHandler;
+    private EventHandler mSessionLostStateHandler;
+
     private OnEventListener mOnEventListener;
     private OnKeyStatusChangeListener mOnKeyStatusChangeListener;
     private OnExpirationUpdateListener mOnExpirationUpdateListener;
+    private OnSessionLostStateListener mOnSessionLostStateListener;
+
+    private final Object mEventLock = new Object();
+    private final Object mKeyStatusChangeLock = new Object();
+    private final Object mExpirationUpdateLock = new Object();
+    private final Object mSessionLostStateLock = new Object();
 
     private long mNativeContext;
 
@@ -200,6 +208,35 @@
     private static final native boolean isCryptoSchemeSupportedNative(
             @NonNull byte[] uuid, @Nullable String mimeType);
 
+    private EventHandler createHandler() {
+        Looper looper;
+        EventHandler handler;
+        if ((looper = Looper.myLooper()) != null) {
+            handler = new EventHandler(this, looper);
+        } else if ((looper = Looper.getMainLooper()) != null) {
+            handler = new EventHandler(this, looper);
+        } else {
+            handler = null;
+        }
+        return handler;
+    }
+
+    private EventHandler updateHandler(Handler handler) {
+        Looper looper;
+        EventHandler newHandler = null;
+        if (handler != null) {
+            looper = handler.getLooper();
+        } else {
+            looper = Looper.myLooper();
+        }
+        if (looper != null) {
+            if (handler == null || handler.getLooper() != looper) {
+                newHandler = new EventHandler(this, looper);
+            }
+        }
+        return newHandler;
+    }
+
     /**
      * Instantiate a MediaDrm object
      *
@@ -209,14 +246,10 @@
      * specified scheme UUID
      */
     public MediaDrm(@NonNull UUID uuid) throws UnsupportedSchemeException {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else {
-            mEventHandler = null;
-        }
+        mEventHandler = createHandler();
+        mKeyStatusChangeHandler = createHandler();
+        mExpirationUpdateHandler = createHandler();
+        mSessionLostStateHandler = createHandler();
 
         /* Native setup requires a weak reference to our object.
          * It's easier to create it here than in C++.
@@ -272,6 +305,40 @@
     }
 
     /**
+     * Thrown when an error occurs in any method that has a session context.
+     */
+    public static final class SessionException extends RuntimeException {
+        public SessionException(int errorCode, @Nullable String detailMessage) {
+            super(detailMessage);
+            mErrorCode = errorCode;
+        }
+
+        /**
+         * This indicates that apps using MediaDrm sessions are
+         * temporarily exceeding the capacity of available crypto
+         * resources. The app should retry the operation later.
+         */
+        public static final int ERROR_RESOURCE_CONTENTION = 1;
+
+        /** @hide */
+        @IntDef({
+            ERROR_RESOURCE_CONTENTION,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface SessionErrorCode {}
+
+        /**
+         * Retrieve the error code associated with the SessionException
+         */
+        @SessionErrorCode
+        public int getErrorCode() {
+            return mErrorCode;
+        }
+
+        private final int mErrorCode;
+    }
+
+    /**
      * Register a callback to be invoked when a session expiration update
      * occurs.  The app's OnExpirationUpdateListener will be notified
      * when the expiration time of the keys in the session have changed.
@@ -282,15 +349,12 @@
      */
     public void setOnExpirationUpdateListener(
             @Nullable OnExpirationUpdateListener listener, @Nullable Handler handler) {
-        if (listener != null) {
-            Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
-            if (looper != null) {
-                if (mEventHandler == null || mEventHandler.getLooper() != looper) {
-                    mEventHandler = new EventHandler(this, looper);
-                }
+        synchronized(mExpirationUpdateLock) {
+            if (listener != null) {
+                mExpirationUpdateHandler = updateHandler(handler);
             }
+            mOnExpirationUpdateListener = listener;
         }
-        mOnExpirationUpdateListener = listener;
     }
 
     /**
@@ -324,15 +388,12 @@
      */
     public void setOnKeyStatusChangeListener(
             @Nullable OnKeyStatusChangeListener listener, @Nullable Handler handler) {
-        if (listener != null) {
-            Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
-            if (looper != null) {
-                if (mEventHandler == null || mEventHandler.getLooper() != looper) {
-                    mEventHandler = new EventHandler(this, looper);
-                }
+        synchronized(mKeyStatusChangeLock) {
+            if (listener != null) {
+                mKeyStatusChangeHandler = updateHandler(handler);
             }
+            mOnKeyStatusChangeListener = listener;
         }
-        mOnKeyStatusChangeListener = listener;
     }
 
     /**
@@ -360,6 +421,46 @@
     }
 
     /**
+     * Register a callback to be invoked when session state has been
+     * lost. This event can occur on devices that are not capable of
+     * retaining crypto session state across device suspend/resume
+     * cycles.  When this event occurs, the session must be closed and
+     * a new session opened to resume operation.
+     *
+     * @param listener the callback that will be run, or {@code null} to unregister the
+     *     previously registered callback.
+     * @param handler the handler on which the listener should be invoked, or
+     *     {@code null} if the listener should be invoked on the calling thread's looper.
+     */
+    public void setOnSessionLostStateListener(
+            @Nullable OnSessionLostStateListener listener, @Nullable Handler handler) {
+        synchronized(mSessionLostStateLock) {
+            if (listener != null) {
+                mSessionLostStateHandler = updateHandler(handler);
+            }
+            mOnSessionLostStateListener = listener;
+        }
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when the
+     * session state has been lost and is now invalid
+     */
+    public interface OnSessionLostStateListener
+    {
+        /**
+         * Called when session state has lost state, to inform the app
+         * about the condition so it can close the session and open a new
+         * one to resume operation.
+         *
+         * @param md the MediaDrm object on which the event occurred
+         * @param sessionId the DRM session ID on which the event occurred
+         */
+        void onSessionLostState(
+                @NonNull MediaDrm md, @NonNull byte[] sessionId);
+    }
+
+    /**
      * Defines the status of a key.
      * A KeyStatus for each key in a session is provided to the
      * {@link OnKeyStatusChangeListener#onKeyStatusChange}
@@ -437,7 +538,9 @@
      */
     public void setOnEventListener(@Nullable OnEventListener listener)
     {
-        mOnEventListener = listener;
+        synchronized(mEventLock) {
+            mOnEventListener = listener;
+        }
     }
 
     /**
@@ -513,6 +616,7 @@
     private static final int DRM_EVENT = 200;
     private static final int EXPIRATION_UPDATE = 201;
     private static final int KEY_STATUS_CHANGE = 202;
+    private static final int SESSION_LOST_STATE = 203;
 
     private class EventHandler extends Handler
     {
@@ -532,52 +636,72 @@
             switch(msg.what) {
 
             case DRM_EVENT:
-                if (mOnEventListener != null) {
-                    if (msg.obj != null && msg.obj instanceof Parcel) {
-                        Parcel parcel = (Parcel)msg.obj;
-                        byte[] sessionId = parcel.createByteArray();
-                        if (sessionId.length == 0) {
-                            sessionId = null;
-                        }
-                        byte[] data = parcel.createByteArray();
-                        if (data.length == 0) {
-                            data = null;
-                        }
+                synchronized(mEventLock) {
+                    if (mOnEventListener != null) {
+                        if (msg.obj != null && msg.obj instanceof Parcel) {
+                            Parcel parcel = (Parcel)msg.obj;
+                            byte[] sessionId = parcel.createByteArray();
+                            if (sessionId.length == 0) {
+                                sessionId = null;
+                            }
+                            byte[] data = parcel.createByteArray();
+                            if (data.length == 0) {
+                                data = null;
+                            }
 
-                        Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
-                        mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
+                            Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")");
+                            mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data);
+                        }
                     }
                 }
                 return;
 
             case KEY_STATUS_CHANGE:
-                if (mOnKeyStatusChangeListener != null) {
-                    if (msg.obj != null && msg.obj instanceof Parcel) {
-                        Parcel parcel = (Parcel)msg.obj;
-                        byte[] sessionId = parcel.createByteArray();
-                        if (sessionId.length > 0) {
-                            List<KeyStatus> keyStatusList = keyStatusListFromParcel(parcel);
-                            boolean hasNewUsableKey = (parcel.readInt() != 0);
+                synchronized(mKeyStatusChangeLock) {
+                    if (mOnKeyStatusChangeListener != null) {
+                        if (msg.obj != null && msg.obj instanceof Parcel) {
+                            Parcel parcel = (Parcel)msg.obj;
+                            byte[] sessionId = parcel.createByteArray();
+                            if (sessionId.length > 0) {
+                                List<KeyStatus> keyStatusList = keyStatusListFromParcel(parcel);
+                                boolean hasNewUsableKey = (parcel.readInt() != 0);
 
-                            Log.i(TAG, "Drm key status changed");
-                            mOnKeyStatusChangeListener.onKeyStatusChange(mMediaDrm, sessionId,
-                                    keyStatusList, hasNewUsableKey);
+                                Log.i(TAG, "Drm key status changed");
+                                mOnKeyStatusChangeListener.onKeyStatusChange(mMediaDrm, sessionId,
+                                        keyStatusList, hasNewUsableKey);
+                            }
                         }
                     }
                 }
                 return;
 
             case EXPIRATION_UPDATE:
-                if (mOnExpirationUpdateListener != null) {
-                    if (msg.obj != null && msg.obj instanceof Parcel) {
-                        Parcel parcel = (Parcel)msg.obj;
-                        byte[] sessionId = parcel.createByteArray();
-                        if (sessionId.length > 0) {
-                            long expirationTime = parcel.readLong();
+                synchronized(mExpirationUpdateLock) {
+                    if (mOnExpirationUpdateListener != null) {
+                        if (msg.obj != null && msg.obj instanceof Parcel) {
+                            Parcel parcel = (Parcel)msg.obj;
+                            byte[] sessionId = parcel.createByteArray();
+                            if (sessionId.length > 0) {
+                                long expirationTime = parcel.readLong();
 
-                            Log.i(TAG, "Drm key expiration update: " + expirationTime);
-                            mOnExpirationUpdateListener.onExpirationUpdate(mMediaDrm, sessionId,
-                                    expirationTime);
+                                Log.i(TAG, "Drm key expiration update: " + expirationTime);
+                                mOnExpirationUpdateListener.onExpirationUpdate(mMediaDrm, sessionId,
+                                        expirationTime);
+                            }
+                        }
+                    }
+                }
+                return;
+
+            case SESSION_LOST_STATE:
+                synchronized(mSessionLostStateLock) {
+                    if (mOnSessionLostStateListener != null) {
+                        if (msg.obj != null && msg.obj instanceof Parcel) {
+                            Parcel parcel = (Parcel)msg.obj;
+                            byte[] sessionId = parcel.createByteArray();
+                            Log.i(TAG, "Drm session lost state event: ");
+                            mOnSessionLostStateListener.onSessionLostState(mMediaDrm,
+                                    sessionId);
                         }
                     }
                 }
@@ -619,9 +743,42 @@
         if (md == null) {
             return;
         }
-        if (md.mEventHandler != null) {
-            Message m = md.mEventHandler.obtainMessage(what, eventType, extra, obj);
-            md.mEventHandler.sendMessage(m);
+        switch (what) {
+            case DRM_EVENT:
+                synchronized(md.mEventLock) {
+                    if (md.mEventHandler != null) {
+                        Message m = md.mEventHandler.obtainMessage(what, eventType, extra, obj);
+                        md.mEventHandler.sendMessage(m);
+                    }
+                }
+                break;
+            case EXPIRATION_UPDATE:
+                synchronized(md.mExpirationUpdateLock) {
+                    if (md.mExpirationUpdateHandler != null) {
+                        Message m = md.mExpirationUpdateHandler.obtainMessage(what, obj);
+                        md.mExpirationUpdateHandler.sendMessage(m);
+                    }
+                }
+                break;
+            case KEY_STATUS_CHANGE:
+                synchronized(md.mKeyStatusChangeLock) {
+                    if (md.mKeyStatusChangeHandler != null) {
+                        Message m = md.mKeyStatusChangeHandler.obtainMessage(what, obj);
+                        md.mKeyStatusChangeHandler.sendMessage(m);
+                    }
+                }
+                break;
+            case SESSION_LOST_STATE:
+                synchronized(md.mSessionLostStateLock) {
+                    if (md.mSessionLostStateHandler != null) {
+                        Message m = md.mSessionLostStateHandler.obtainMessage(what, obj);
+                        md.mSessionLostStateHandler.sendMessage(m);
+                    }
+                }
+                break;
+            default:
+                Log.e(TAG, "Unknown message type " + what);
+                break;
         }
     }
 
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 7b20f7a..e008adf 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -19,7 +19,7 @@
 import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
 import static android.media.MediaConstants.KEY_PACKAGE_NAME;
 import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_SESSION2_STUB;
+import static android.media.MediaConstants.KEY_SESSION2LINK;
 import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
 import static android.media.Session2Command.RESULT_INFO_SKIPPED;
 import static android.media.Session2Token.TYPE_SESSION;
@@ -56,10 +56,9 @@
  * 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.
- * @hide
  */
 public class MediaSession2 implements AutoCloseable {
-    static final String TAG = "MediaSession";
+    static final String TAG = "MediaSession2";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     // Note: This checks the uniqueness of a session ID only in a single process.
@@ -89,7 +88,6 @@
     private final Handler mResultHandler;
 
     //@GuardedBy("mLock")
-    @SuppressWarnings("WeakerAccess") /* synthetic access */
     private boolean mClosed;
 
     MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity,
@@ -113,6 +111,7 @@
                 Context.MEDIA_SESSION_SERVICE);
         // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
         mResultHandler = new Handler(context.getMainLooper());
+        mClosed = false;
     }
 
     @Override
@@ -179,6 +178,7 @@
      * @return a token which will be sent together in {@link SessionCallback#onCommandResult}
      *     when its result is received.
      */
+    @NonNull
     public Object sendSessionCommand(@NonNull ControllerInfo controller,
             @NonNull Session2Command command, @Nullable Bundle args) {
         if (controller == null) {
@@ -206,7 +206,10 @@
      * @param controller the controller to get the session command
      * @param token the token which is returned from {@link #sendSessionCommand}.
      */
-    public void cancelSessionCommand(ControllerInfo controller, Object token) {
+    public void cancelSessionCommand(@NonNull ControllerInfo controller, @NonNull Object token) {
+        if (controller == null) {
+            throw new IllegalArgumentException("controller shouldn't be null");
+        }
         if (token == null) {
             throw new IllegalArgumentException("token shouldn't be null");
         }
@@ -267,7 +270,7 @@
                     // It's needed because we cannot call synchronous calls between
                     // session/controller.
                     Bundle connectionResult = new Bundle();
-                    connectionResult.putParcelable(KEY_SESSION2_STUB, mSessionStub);
+                    connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
                     connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
                             controllerInfo.mAllowedCommands);
 
@@ -558,7 +561,7 @@
         }
 
         @Override
-        public boolean equals(Object obj) {
+        public boolean equals(@Nullable Object obj) {
             if (!(obj instanceof ControllerInfo)) return false;
             if (this == obj) return true;
 
@@ -570,6 +573,7 @@
         }
 
         @Override
+        @NonNull
         public String toString() {
             return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid="
                     + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})";
@@ -693,7 +697,7 @@
          * @return the result for the session command. A runtime exception will be thrown if null
          *         is returned.
          */
-        @NonNull
+        @Nullable
         public Session2Command.Result onSessionCommand(@NonNull MediaSession2 session,
                 @NonNull ControllerInfo controller, @NonNull Session2Command command,
                 @Nullable Bundle args) {
diff --git a/media/java/android/media/Session2CommandGroup.java b/media/java/android/media/Session2CommandGroup.java
index 519888e..a189c26 100644
--- a/media/java/android/media/Session2CommandGroup.java
+++ b/media/java/android/media/Session2CommandGroup.java
@@ -59,6 +59,7 @@
      *
      * @param commands The collection of commands to copy.
      */
+    @SuppressWarnings("WeakerAccess") /* synthetic access */
     Session2CommandGroup(@Nullable Collection<Session2Command> commands) {
         if (commands != null) {
             mCommands.addAll(commands);
diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java
index e1fff38..95ee4c0 100644
--- a/media/java/android/media/Session2Token.java
+++ b/media/java/android/media/Session2Token.java
@@ -34,7 +34,7 @@
 import java.util.Objects;
 
 /**
- * Represents an ongoing {@link MediaSession2} or a {@link MediaSession2Service}.
+ * Represents an ongoing {@link MediaSession2} or a MediaSession2Service.
  * If it's representing a session service, it may not be ongoing.
  * <p>
  * This API is not generally intended for third party application developers.
@@ -45,9 +45,8 @@
  * This may be passed to apps by the session owner to allow them to create a
  * {@link MediaController2} to communicate with the session.
  * <p>
- * It can be also obtained by {@link MediaSessionManager}.
+ * It can be also obtained by {@link android.media.session.MediaSessionManager}.
  *
- * @hide
  */
 // New version of MediaSession2.Token for following reasons
 //   - Stop implementing Parcelable for updatable support
@@ -56,6 +55,7 @@
 //     This helps controller apps to keep target of dispatching media key events in uniform way.
 //     For details about the reason, see following. (Android O+)
 //         android.media.session.MediaSessionManager.Callback#onAddressedPlayerChanged
+// TODO: use @link for MediaSession2Service
 public final class Session2Token implements Parcelable {
     private static final String TAG = "Session2Token";
 
@@ -75,7 +75,7 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
+    @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE})
     public @interface TokenType {
     }
 
@@ -85,15 +85,10 @@
     public static final int TYPE_SESSION = 0;
 
     /**
-     * Type for {@link MediaSession2Service}.
+     * Type for MediaSession2Service.
      */
     public static final int TYPE_SESSION_SERVICE = 1;
 
-    /**
-     * Type for {@link MediaLibrary2Service}.
-     */
-    public static final int TYPE_LIBRARY_SERVICE = 2;
-
     private final int mUid;
     private final @TokenType int mType;
     private final String mPackageName;
@@ -102,8 +97,7 @@
     private final ComponentName mComponentName;
 
     /**
-     * Constructor for the token with type {@link #TYPE_SESSION_SERVICE} or
-     * {@link #TYPE_LIBRARY_SERVICE}.
+     * Constructor for the token with type {@link #TYPE_SESSION_SERVICE}.
      *
      * @param context The context.
      * @param serviceComponent The component name of the service.
@@ -239,7 +233,6 @@
      * @return type of the token
      * @see #TYPE_SESSION
      * @see #TYPE_SESSION_SERVICE
-     * @see #TYPE_LIBRARY_SERVICE
      */
     public @TokenType int getType() {
         return mType;
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index d6b6339..452c6e1 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -34,7 +34,6 @@
         "libutils",
         "libbinder",
         "libmedia",
-        "libmediaextractor",
         "libmedia_omx",
         "libmediametrics",
         "libmediadrm",
@@ -125,12 +124,12 @@
         "libcutils",
         "libmedia_helper",
         "libmedia_player2_util",
-        "libmediaextractor",
         "libmediaplayer2",
         "libmediaplayer2-protos",
         "libmediandk_utils",
         "libmediautils",
         "libprotobuf-cpp-lite",
+        "libstagefright",
         "libstagefright_esds",
         "libstagefright_foundation",
         "libstagefright_httplive",
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 2578608..7b07bea3 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -72,7 +72,10 @@
     jint cryptoErrorResourceBusy;
     jint cryptoErrorInsufficientOutputProtection;
     jint cryptoErrorSessionNotOpened;
+    jint cryptoErrorInsufficientSecurity;
     jint cryptoErrorUnsupportedOperation;
+    jint cryptoErrorFrameTooLarge;
+    jint cryptoErrorLostState;
 } gCryptoErrorCodes;
 
 static struct CodecActionCodes {
@@ -1005,10 +1008,22 @@
             err = gCryptoErrorCodes.cryptoErrorSessionNotOpened;
             defaultMsg = "Attempted to use a closed session";
             break;
+        case ERROR_DRM_INSUFFICIENT_SECURITY:
+            err = gCryptoErrorCodes.cryptoErrorInsufficientSecurity;
+            defaultMsg = "Required security level is not met";
+            break;
         case ERROR_DRM_CANNOT_HANDLE:
             err = gCryptoErrorCodes.cryptoErrorUnsupportedOperation;
             defaultMsg = "Operation not supported in this configuration";
             break;
+        case ERROR_DRM_FRAME_TOO_LARGE:
+            err = gCryptoErrorCodes.cryptoErrorFrameTooLarge;
+            defaultMsg = "Decrytped frame exceeds size of output buffer";
+            break;
+        case ERROR_DRM_SESSION_LOST_STATE:
+            err = gCryptoErrorCodes.cryptoErrorLostState;
+            defaultMsg = "Session state was lost, open a new session and retry";
+            break;
         default:  /* Other negative DRM error codes go out as is. */
             break;
     }
@@ -1994,11 +2009,26 @@
     gCryptoErrorCodes.cryptoErrorSessionNotOpened =
         env->GetStaticIntField(clazz.get(), field);
 
+    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_SECURITY", "I");
+    CHECK(field != NULL);
+    gCryptoErrorCodes.cryptoErrorInsufficientSecurity =
+        env->GetStaticIntField(clazz.get(), field);
+
     field = env->GetStaticFieldID(clazz.get(), "ERROR_UNSUPPORTED_OPERATION", "I");
     CHECK(field != NULL);
     gCryptoErrorCodes.cryptoErrorUnsupportedOperation =
         env->GetStaticIntField(clazz.get(), field);
 
+    field = env->GetStaticFieldID(clazz.get(), "ERROR_FRAME_TOO_LARGE", "I");
+    CHECK(field != NULL);
+    gCryptoErrorCodes.cryptoErrorFrameTooLarge =
+        env->GetStaticIntField(clazz.get(), field);
+
+    field = env->GetStaticFieldID(clazz.get(), "ERROR_LOST_STATE", "I");
+    CHECK(field != NULL);
+    gCryptoErrorCodes.cryptoErrorLostState =
+        env->GetStaticIntField(clazz.get(), field);
+
     clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
     CHECK(clazz.get() != NULL);
     field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index be71dad5..8336459 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -110,6 +110,7 @@
     jint kWhatDrmEvent;
     jint kWhatExpirationUpdate;
     jint kWhatKeyStatusChange;
+    jint kWhatSessionLostState;
 } gEventWhat;
 
 struct KeyTypes {
@@ -141,6 +142,16 @@
     jclass classId;
 };
 
+struct SessionExceptionFields {
+    jmethodID init;
+    jclass classId;
+    jfieldID errorCode;
+};
+
+struct SessionExceptionErrorCodes {
+    jint kResourceContention;
+} gSessionExceptionErrorCodes;
+
 struct HDCPLevels {
     jint kHdcpLevelUnknown;
     jint kHdcpNone;
@@ -180,6 +191,7 @@
     EntryFields entry;
     CertificateFields certificate;
     StateExceptionFields stateException;
+    SessionExceptionFields sessionException;
     jclass certificateClassId;
     jclass hashmapClassId;
     jclass arraylistClassId;
@@ -310,6 +322,9 @@
          case DrmPlugin::kDrmPluginEventKeysChange:
             jwhat = gEventWhat.kWhatKeyStatusChange;
             break;
+         case DrmPlugin::kDrmPluginEventSessionLostState:
+            jwhat = gEventWhat.kWhatSessionLostState;
+            break;
         default:
             ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
             return;
@@ -343,6 +358,30 @@
     env->Throw(static_cast<jthrowable>(exception));
 }
 
+static void throwSessionException(JNIEnv *env, const char *msg, status_t err) {
+    ALOGE("Session exception: %s (%d)", msg, err);
+
+    jint jErrorCode = 0;
+    switch(err) {
+        case ERROR_DRM_RESOURCE_CONTENTION:
+            jErrorCode = gSessionExceptionErrorCodes.kResourceContention;
+            break;
+        default:
+            break;
+    }
+
+    jobject exception = env->NewObject(gFields.sessionException.classId,
+            gFields.sessionException.init, static_cast<int>(err),
+            env->NewStringUTF(msg));
+
+    env->SetIntField(exception, gFields.sessionException.errorCode, jErrorCode);
+    env->Throw(static_cast<jthrowable>(exception));
+}
+
+static bool isSessionException(status_t err) {
+    return err == ERROR_DRM_RESOURCE_CONTENTION;
+}
+
 static bool throwExceptionAsNecessary(
         JNIEnv *env, status_t err, const char *msg = NULL) {
 
@@ -370,7 +409,7 @@
     case ERROR_DRM_CANNOT_HANDLE:
         drmMessage = "Invalid parameter or data format";
         break;
-    case ERROR_DRM_TAMPER_DETECTED:
+    case ERROR_DRM_INVALID_STATE:
         drmMessage = "Invalid state";
         break;
     default:
@@ -399,6 +438,9 @@
         jniThrowException(env, "android/media/MediaDrmResetException",
                 "mediaserver died");
         return true;
+    } else if (isSessionException(err)) {
+        throwSessionException(env, msg, err);
+        return true;
     } else if (err != OK) {
         String8 errbuf;
         if (drmMessage != NULL) {
@@ -705,6 +747,8 @@
     gEventWhat.kWhatExpirationUpdate = env->GetStaticIntField(clazz, field);
     GET_STATIC_FIELD_ID(field, clazz, "KEY_STATUS_CHANGE", "I");
     gEventWhat.kWhatKeyStatusChange = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "SESSION_LOST_STATE", "I");
+    gEventWhat.kWhatSessionLostState = env->GetStaticIntField(clazz, field);
 
     GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
     gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
@@ -831,6 +875,14 @@
     FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
     GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
     gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+    FIND_CLASS(clazz, "android/media/MediaDrm$SessionException");
+    GET_METHOD_ID(gFields.sessionException.init, clazz, "<init>", "(ILjava/lang/String;)V");
+    gFields.sessionException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+    GET_FIELD_ID(gFields.sessionException.errorCode, clazz, "mErrorCode", "I");
+
+    GET_STATIC_FIELD_ID(field, clazz, "ERROR_RESOURCE_CONTENTION", "I");
+    gSessionExceptionErrorCodes.kResourceContention = env->GetStaticIntField(clazz, field);
 }
 
 static void android_media_MediaDrm_native_setup(
diff --git a/native/android/Android.bp b/native/android/Android.bp
index fdcfc44..73d4c45 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -49,6 +49,7 @@
         "sharedmem.cpp",
         "storage_manager.cpp",
         "surface_texture.cpp",
+        "surface_control.cpp",
         "system_fonts.cpp",
         "trace.cpp",
     ],
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 537aed4..8be8eda 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -205,6 +205,9 @@
     AStorageManager_mountObb;
     AStorageManager_new;
     AStorageManager_unmountObb;
+    ASurfaceControl_create; # introduced=29
+    ASurfaceControl_createFromWindow; # introduced=29
+    ASurfaceControl_destroy; # introduced=29
     ASurfaceTexture_acquireANativeWindow; # introduced=28
     ASurfaceTexture_attachToGLContext; # introduced=28
     ASurfaceTexture_detachFromGLContext; # introduced=28
@@ -213,6 +216,16 @@
     ASurfaceTexture_getTransformMatrix; # introduced=28
     ASurfaceTexture_release; # introduced=28
     ASurfaceTexture_updateTexImage; # introduced=28
+    ASurfaceTransaction_apply; # introduced=29
+    ASurfaceTransaction_create; # introduced=29
+    ASurfaceTransaction_delete; # introduced=29
+    ASurfaceTransaction_setBuffer; # introduced=29
+    ASurfaceTransaction_setBufferTransparency; # introduced=29
+    ASurfaceTransaction_setDamageRegion; # introduced=29
+    ASurfaceTransaction_setGeometry; # introduced=29
+    ASurfaceTransaction_setOnComplete; # introduced=29
+    ASurfaceTransaction_setVisibility; # introduced=29
+    ASurfaceTransaction_setZOrder; # introduced=29
     ASystemFontIterator_open; # introduced=29
     ASystemFontIterator_close; # introduced=29
     ASystemFontIterator_next; # introduced=29
diff --git a/native/android/sharedmem.cpp b/native/android/sharedmem.cpp
index 757aaec..4410bd6 100644
--- a/native/android/sharedmem.cpp
+++ b/native/android/sharedmem.cpp
@@ -71,7 +71,7 @@
     }
     int fd = env->CallIntMethod(javaSharedMemory, sSharedMemory.getFd);
     if (fd != -1) {
-        fd = dup(fd);
+        fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
     }
     return fd;
 }
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
new file mode 100644
index 0000000..ead5b0b
--- /dev/null
+++ b/native/android/surface_control.cpp
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#include <android/native_window.h>
+#include <android/surface_control.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SurfaceControl.h>
+
+using namespace android;
+
+using Transaction = SurfaceComposerClient::Transaction;
+
+#define CHECK_NOT_NULL(name) \
+    LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
+
+#define CHECK_VALID_RECT(name)                                     \
+    LOG_ALWAYS_FATAL_IF(!static_cast<const Rect&>(name).isValid(), \
+                        "invalid arg passed as " #name " argument");
+
+Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) {
+    return reinterpret_cast<Transaction*>(aSurfaceTransaction);
+}
+
+SurfaceControl* ASurfaceControl_to_SurfaceControl(ASurfaceControl* aSurfaceControl) {
+    return reinterpret_cast<SurfaceControl*>(aSurfaceControl);
+}
+
+void SurfaceControl_acquire(SurfaceControl* surfaceControl) {
+    // incStrong/decStrong token must be the same, doesn't matter what it is
+    surfaceControl->incStrong((void*)SurfaceControl_acquire);
+}
+
+void SurfaceControl_release(SurfaceControl* surfaceControl) {
+    // incStrong/decStrong token must be the same, doesn't matter what it is
+    surfaceControl->decStrong((void*)SurfaceControl_acquire);
+}
+
+ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const char* debug_name) {
+    CHECK_NOT_NULL(window);
+    CHECK_NOT_NULL(debug_name);
+
+    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
+    if (client->initCheck() != NO_ERROR) {
+        return nullptr;
+    }
+
+    uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
+    sp<SurfaceControl> surfaceControl =
+            client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */,
+                                            // Format is only relevant for buffer queue layers.
+                                            PIXEL_FORMAT_UNKNOWN /* format */, flags,
+                                            static_cast<Surface*>(window));
+    if (!surfaceControl) {
+        return nullptr;
+    }
+
+    SurfaceControl_acquire(surfaceControl.get());
+    return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
+}
+
+ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name) {
+    CHECK_NOT_NULL(parent);
+    CHECK_NOT_NULL(debug_name);
+
+    SurfaceComposerClient* client = ASurfaceControl_to_SurfaceControl(parent)->getClient().get();
+
+    SurfaceControl* surfaceControlParent = ASurfaceControl_to_SurfaceControl(parent);
+
+    uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
+    sp<SurfaceControl> surfaceControl =
+            client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */,
+                                  // Format is only relevant for buffer queue layers.
+                                  PIXEL_FORMAT_UNKNOWN /* format */, flags,
+                                  surfaceControlParent);
+    if (!surfaceControl) {
+        return nullptr;
+    }
+
+    SurfaceControl_acquire(surfaceControl.get());
+    return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
+}
+
+void ASurfaceControl_destroy(ASurfaceControl* aSurfaceControl) {
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+
+    Transaction().reparent(surfaceControl, nullptr).apply();
+    SurfaceControl_release(surfaceControl.get());
+}
+
+ASurfaceTransaction* ASurfaceTransaction_create() {
+    Transaction* transaction = new Transaction;
+    return reinterpret_cast<ASurfaceTransaction*>(transaction);
+}
+
+void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) {
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+    delete transaction;
+}
+
+void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->apply();
+}
+
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context,
+                                       ASurfaceTransaction_OnComplete func) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(context);
+    CHECK_NOT_NULL(func);
+
+    TransactionCompletedCallbackTakesContext callback = [func](void* callback_context,
+                                                               const TransactionStats& stats) {
+        int fence = (stats.presentFence) ? stats.presentFence->dup() : -1;
+        (*func)(callback_context, fence);
+    };
+
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->addTransactionCompletedCallback(callback, context);
+}
+
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+                                       int8_t visibility) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    switch (visibility) {
+    case ASURFACE_TRANSACTION_VISIBILITY_SHOW:
+        transaction->show(surfaceControl);
+        break;
+    case ASURFACE_TRANSACTION_VISIBILITY_HIDE:
+        transaction->hide(surfaceControl);
+        break;
+    default:
+        LOG_ALWAYS_FATAL("invalid visibility %d", visibility);
+    }
+}
+
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+                                   int32_t z_order) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->setLayer(surfaceControl, z_order);
+}
+
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+                                   AHardwareBuffer* buffer, int fence_fd) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    sp<GraphicBuffer> graphic_buffer(reinterpret_cast<GraphicBuffer*>(buffer));
+
+    transaction->setBuffer(surfaceControl, graphic_buffer);
+    if (fence_fd != -1) {
+        sp<Fence> fence = new Fence(fence_fd);
+        transaction->setAcquireFence(surfaceControl, fence);
+    }
+}
+
+void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction,
+                                     ASurfaceControl* aSurfaceControl, const ARect& source,
+                                     const ARect& destination, int32_t transform) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+    CHECK_VALID_RECT(source);
+    CHECK_VALID_RECT(destination);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->setCrop(surfaceControl, static_cast<const Rect&>(source));
+    transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));
+    transaction->setTransform(surfaceControl, transform);
+}
+
+void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
+                                               ASurfaceControl* aSurfaceControl,
+                                               int8_t transparency) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    uint32_t flags = (transparency == ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE) ?
+                      layer_state_t::eLayerOpaque : 0;
+    transaction->setFlags(surfaceControl, flags, layer_state_t::eLayerOpaque);
+}
+
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+                                         const ARect rects[], uint32_t count) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    Region region;
+    for (uint32_t i = 0; i < count; ++i) {
+        region.merge(static_cast<const Rect&>(rects[i]));
+    }
+
+    transaction->setSurfaceDamageRegion(surfaceControl, region);
+}
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index 6afd883..bb2ee9b 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -109,8 +109,15 @@
   // Input: Format of the destination surface.
   VkFormat format;
 
-  // Input: Color space transformation from linear RGB to D50-adapted XYZ
-  float matrix[9];
+  // Input: Color space parameters.
+  float transfer_function_g;
+  float transfer_function_a;
+  float transfer_function_b;
+  float transfer_function_c;
+  float transfer_function_d;
+  float transfer_function_e;
+  float transfer_function_f;
+  float color_space_toXYZD50[9];
 
   // Input: current clip rect
   int clip_left;
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index a9d8f62..95df5f2 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -27,6 +27,7 @@
 import android.service.notification.NotificationAssistantService;
 import android.text.TextUtils;
 import android.util.LruCache;
+import android.view.textclassifier.ConversationAction;
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
@@ -65,13 +66,13 @@
     private static final int MAX_MESSAGES_TO_EXTRACT = 5;
     private static final int MAX_RESULT_ID_TO_CACHE = 20;
 
-    private static final ConversationActions.TypeConfig TYPE_CONFIG =
-            new ConversationActions.TypeConfig.Builder().setIncludedTypes(
-                    Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+    private static final TextClassifier.EntityConfig TYPE_CONFIG =
+            new TextClassifier.EntityConfig.Builder().setIncludedTypes(
+                    Collections.singletonList(ConversationAction.TYPE_TEXT_REPLY))
                     .includeTypesFromTextClassifier(false)
                     .build();
     private static final List<String> HINTS =
-            Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION);
+            Collections.singletonList(ConversationActions.Request.HINT_FOR_NOTIFICATION);
 
     private Context mContext;
     @Nullable
@@ -137,7 +138,7 @@
 
         ConversationActions conversationActionsResult =
                 mTextClassifier.suggestConversationActions(request);
-        List<ConversationActions.ConversationAction> conversationActions =
+        List<ConversationAction> conversationActions =
                 conversationActionsResult.getConversationActions();
         ArrayList<CharSequence> replies = conversationActions.stream()
                 .map(conversationAction -> conversationAction.getTextReply())
@@ -193,7 +194,7 @@
         }
         TextClassifierEvent textClassifierEvent =
                 createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
-                        .setEntityType(ConversationActions.TYPE_TEXT_REPLY)
+                        .setEntityType(ConversationAction.TYPE_TEXT_REPLY)
                         .build();
         mTextClassifier.onTextClassifierEvent(textClassifierEvent);
     }
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
index 7d74788..7b7ce3d 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
@@ -32,6 +32,7 @@
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
+import android.view.textclassifier.ConversationAction;
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
@@ -65,9 +66,10 @@
     private static final String NOTIFICATION_KEY = "key";
     private static final String RESULT_ID = "id";
 
-    private static final ConversationActions.ConversationAction REPLY_ACTION =
-            new ConversationActions.ConversationAction.Builder(
-                    ConversationActions.TYPE_TEXT_REPLY).setTextReply("Home").build();
+    private static final ConversationAction REPLY_ACTION =
+            new ConversationAction.Builder(ConversationAction.TYPE_TEXT_REPLY)
+            .setTextReply("Home")
+            .build();
 
     private SmartActionsHelper mSmartActionsHelper;
     private Context mContext;
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 0b0f1ec..7f8bb93 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -20,6 +20,7 @@
           package="com.android.mainline.networkstack"
           android:sharedUserId="android.uid.networkstack">
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 94ea1b9..4077d93 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -545,7 +545,9 @@
                     return HANDLED;
                 case CMD_FORCE_REEVALUATION:
                 case CMD_CAPTIVE_PORTAL_RECHECK:
-                    log("Forcing reevaluation for UID " + message.arg1);
+                    final int dnsCount = mDnsStallDetector.getConsecutiveTimeoutCount();
+                    validationLog("Forcing reevaluation for UID " + message.arg1
+                            + ". Dns signal count: " + dnsCount);
                     mUidResponsibleForReeval = message.arg1;
                     transitionTo(mEvaluatingState);
                     return HANDLED;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
index aed02a2..8090169 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
@@ -41,10 +41,6 @@
     private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
     private long mVisibleTimestamp;
 
-    private VisibilityLoggerMixin() {
-        mMetricsCategory = METRICS_CATEGORY_UNKNOWN;
-    }
-
     public VisibilityLoggerMixin(int metricsCategory, MetricsFeatureProvider metricsFeature) {
         mMetricsCategory = metricsCategory;
         mMetricsFeature = metricsFeature;
@@ -81,12 +77,4 @@
                 MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY,
                 MetricsProto.MetricsEvent.VIEW_UNKNOWN);
     }
-
-    /** Returns elapsed time since onResume() */
-    public long elapsedTimeSinceVisible() {
-        if (mVisibleTimestamp == 0) {
-            return 0;
-        }
-        return SystemClock.elapsedRealtime() - mVisibleTimestamp;
-    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index e853399..ef90dc9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -28,8 +28,8 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteStatement;
-import android.media.AudioSystem;
 import android.media.AudioManager;
+import android.media.AudioSystem;
 import android.net.ConnectivityManager;
 import android.os.Build;
 import android.os.Environment;
@@ -1104,9 +1104,7 @@
         }
 
         if (upgradeVersion == 77) {
-            // Introduce "vibrate when ringing" setting
-            loadVibrateWhenRingingSetting(db);
-
+            // "vibrate when ringing" setting moved to SettingsProvider version 168
             upgradeVersion = 78;
         }
 
@@ -2223,8 +2221,6 @@
         } finally {
             if (stmt != null) stmt.close();
         }
-
-        loadVibrateWhenRingingSetting(db);
     }
 
     private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
@@ -2250,24 +2246,6 @@
         }
     }
 
-    private void loadVibrateWhenRingingSetting(SQLiteDatabase db) {
-        // The default should be off. VIBRATE_SETTING_ONLY_SILENT should also be ignored here.
-        // Phone app should separately check whether AudioManager#getRingerMode() returns
-        // RINGER_MODE_VIBRATE, with which the device should vibrate anyway.
-        int vibrateSetting = getIntValueFromSystem(db, Settings.System.VIBRATE_ON,
-                AudioManager.VIBRATE_SETTING_OFF);
-        boolean vibrateWhenRinging = ((vibrateSetting & 3) == AudioManager.VIBRATE_SETTING_ON);
-
-        SQLiteStatement stmt = null;
-        try {
-            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
-                    + " VALUES(?,?);");
-            loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, vibrateWhenRinging ? 1 : 0);
-        } finally {
-            if (stmt != null) stmt.close();
-        }
-    }
-
     private void loadSettings(SQLiteDatabase db) {
         loadSystemSettings(db);
         loadSecureSettings(db);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fa95bf2..9b775e0 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -129,6 +129,7 @@
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
+    <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
     <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 2530abc..afb9781 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -56,6 +56,7 @@
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.annotation.MainThread;
+import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.app.AlertDialog;
 import android.app.Notification;
@@ -799,6 +800,18 @@
             Log.wtf(TAG, "Missing " + EXTRA_BUGREPORT + " on intent " + intent);
             return;
         }
+        final int max = intent.getIntExtra(EXTRA_MAX, -1);
+        final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
+        final String shareTitle = intent.getStringExtra(EXTRA_TITLE);
+        final String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
+        onBugreportFinished(id, bugreportFile, screenshotFile, shareTitle, shareDescription, max);
+    }
+
+    /**
+     * Wraps up bugreport generation and triggers a notification to share the bugreport.
+     */
+    private void onBugreportFinished(int id, File bugreportFile, @Nullable File screenshotFile,
+        String shareTitle, String shareDescription, int max) {
         mInfoDialog.onBugreportFinished();
         BugreportInfo info = getInfo(id);
         if (info == null) {
@@ -809,22 +822,17 @@
         }
         info.renameScreenshots(mScreenshotsDir);
         info.bugreportFile = bugreportFile;
+        if (screenshotFile != null) {
+            info.addScreenshot(screenshotFile);
+        }
 
-        final int max = intent.getIntExtra(EXTRA_MAX, -1);
         if (max != -1) {
             MetricsLogger.histogram(this, "dumpstate_duration", max);
             info.max = max;
         }
 
-        final File screenshot = getFileExtra(intent, EXTRA_SCREENSHOT);
-        if (screenshot != null) {
-            info.addScreenshot(screenshot);
-        }
-
-        final String shareTitle = intent.getStringExtra(EXTRA_TITLE);
         if (!TextUtils.isEmpty(shareTitle)) {
             info.title = shareTitle;
-            final String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
             if (!TextUtils.isEmpty(shareDescription)) {
                 info.shareDescription= shareDescription;
             }
@@ -1944,6 +1952,23 @@
         }
 
         @Override
+        public void onProgress(int progress) throws RemoteException {
+            // TODO(b/111441001): change max argument?
+            updateProgressInfo(progress, CAPPED_MAX);
+        }
+
+        @Override
+        public void onError(int errorCode) throws RemoteException {
+            // TODO(b/111441001): implement
+        }
+
+        @Override
+        public void onFinished(long durationMs, String title, String description)
+                throws RemoteException {
+            // TODO(b/111441001): implement
+        }
+
+        @Override
         public void onProgressUpdated(int progress) throws RemoteException {
             /*
              * Checks whether the progress changed in a way that should be displayed to the user:
@@ -1964,21 +1989,7 @@
             }
 
             if (newPercentage > oldPercentage) {
-                if (DEBUG) {
-                    if (progress != info.progress) {
-                        Log.v(TAG, "Updating progress for PID " + info.pid + "(id: " + info.id
-                                + ") from " + info.progress + " to " + progress);
-                    }
-                    if (max != info.max) {
-                        Log.v(TAG, "Updating max progress for PID " + info.pid + "(id: " + info.id
-                                + ") from " + info.max + " to " + max);
-                    }
-                }
-                info.progress = progress;
-                info.max = max;
-                info.lastUpdate = System.currentTimeMillis();
-
-                updateProgress(info);
+                updateProgressInfo(progress, max);
             }
         }
 
@@ -2000,5 +2011,23 @@
         public void dump(String prefix, PrintWriter pw) {
             pw.print(prefix); pw.print("token: "); pw.println(token);
         }
+
+        private void updateProgressInfo(int progress, int max) {
+            if (DEBUG) {
+                if (progress != info.progress) {
+                    Log.v(TAG, "Updating progress for PID " + info.pid + "(id: " + info.id
+                            + ") from " + info.progress + " to " + progress);
+                }
+                if (max != info.max) {
+                    Log.v(TAG, "Updating max progress for PID " + info.pid + "(id: " + info.id
+                            + ") from " + info.max + " to " + max);
+                }
+            }
+            info.progress = progress;
+            info.max = max;
+            info.lastUpdate = System.currentTimeMillis();
+
+            updateProgress(info);
+        }
     }
 }
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 1c1a140..b4f2711 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -87,6 +87,7 @@
     <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
     <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
     <uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
+    <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
index ecfbfb4..c8e0845 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
@@ -25,12 +25,18 @@
     android:focusable="true"
     android:layout_gravity="center_vertical">
 
-    <ImageView
-        android:id="@+id/app_icon"
+    <FrameLayout
         android:layout_height="@dimen/ongoing_appops_dialog_app_icon_size"
         android:layout_width="@dimen/ongoing_appops_dialog_app_icon_size"
-        android:layout_gravity="start|center_vertical"
-    />
+        android:layout_gravity="start|center_vertical">
+
+        <ImageView
+            android:id="@+id/app_icon"
+            android:layout_height="@dimen/ongoing_appops_dialog_app_icon_size"
+            android:layout_width="@dimen/ongoing_appops_dialog_app_icon_size"
+            android:layout_gravity="center"
+            />
+    </FrameLayout>
 
     <TextView
         android:id="@+id/app_name"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ef16bca..5a00b45 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -952,6 +952,8 @@
     <dimen name="ongoing_appops_dialog_icon_margin">8dp</dimen>
     <!-- Height and width of Application icons in Ongoing App Ops dialog -->
     <dimen name="ongoing_appops_dialog_app_icon_size">32dp</dimen>
+    <!-- Height and width of Plus sign in Ongoing App Ops dialog -->
+    <dimen name="ongoing_appops_dialog_app_plus_size">24dp</dimen>
     <!-- Height of line in Ongoing App Ops dialog-->
     <dimen name="ongoing_appops_dialog_line_height">48dp</dimen>
     <!-- Side margin of title in Ongoing App Ops dialog -->
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index 6ed1eba..77e25e3 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -20,6 +20,7 @@
 import android.content.DialogInterface
 import android.content.Intent
 import android.content.res.ColorStateList
+import android.util.IconDrawableFactory
 import android.view.Gravity
 import android.view.LayoutInflater
 import android.view.View
@@ -37,11 +38,22 @@
 
     private val iconSize = context.resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_dialog_icon_size)
+    private val plusSize = context.resources.getDimensionPixelSize(
+            R.dimen.ongoing_appops_dialog_app_plus_size)
     private val iconColor = context.resources.getColor(
             com.android.internal.R.color.text_color_primary, context.theme)
+    private val plusColor: Int
     private val iconMargin = context.resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_dialog_icon_margin)
     private val MAX_ITEMS = context.resources.getInteger(R.integer.ongoing_appops_dialog_max_apps)
+    private val iconFactory = IconDrawableFactory.newInstance(context, true)
+
+    init {
+        val a = context.theme.obtainStyledAttributes(
+                intArrayOf(com.android.internal.R.attr.colorAccent))
+        plusColor = a.getColor(0, 0)
+        a.recycle()
+    }
 
     fun createDialog(): Dialog {
         val builder = AlertDialog.Builder(context).apply {
@@ -87,9 +99,15 @@
                     numItems - MAX_ITEMS
             )
             val overflowPlus = overflow.findViewById(R.id.app_icon) as ImageView
+            val lp = overflowPlus.layoutParams.apply {
+                height = plusSize
+                width = plusSize
+            }
+            overflowPlus.layoutParams = lp
             overflowPlus.apply {
-                imageTintList = ColorStateList.valueOf(iconColor)
-                setImageDrawable(context.getDrawable(R.drawable.plus))
+                val plus = context.getDrawable(R.drawable.plus)
+                imageTintList = ColorStateList.valueOf(plusColor)
+                setImageDrawable(plus)
             }
         }
 
@@ -114,7 +132,7 @@
         }
 
         app.icon.let {
-            appIcon.setImageDrawable(it)
+            appIcon.setImageDrawable(iconFactory.getShadowedIcon(it))
         }
 
         appName.text = app.applicationName
diff --git a/packages/WallpaperCropper/Android.mk b/packages/WallpaperCropper/Android.mk
index 848f2bd..2fa1dde 100644
--- a/packages/WallpaperCropper/Android.mk
+++ b/packages/WallpaperCropper/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_PACKAGE_NAME := WallpaperCropper
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
+LOCAL_PRODUCT_MODULE := true
 LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/packages/WallpaperCropper/CleanSpec.mk b/packages/WallpaperCropper/CleanSpec.mk
new file mode 100644
index 0000000..e6d8d5a
--- /dev/null
+++ b/packages/WallpaperCropper/CleanSpec.mk
@@ -0,0 +1,50 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/WallpaperCropper)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 5b45a08..44edb56 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6794,6 +6794,13 @@
     // OS: Q
     NOTIFICATION_BLOCKING_HELPER = 1621;
 
+    // ACTION: Tap & Pay -> Default Application Setting -> Use Forground
+    // OS: Q
+    ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622;
+
+    // ACTION: Tap & Pay -> Default Application Setting -> Use Default
+    // OS: Q
+    ACTION_NFC_PAYMENT_ALWAYS_SETTING = 1623;
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index e4ce62d..4a1e5b9 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -23,9 +23,9 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
 import android.os.Build;
@@ -49,9 +49,8 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
-
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * We back up the signatures of each package so that during a system restore,
@@ -95,6 +94,7 @@
     // is coming from pre-Android P device.
     private static final int UNDEFINED_ANCESTRAL_RECORD_VERSION = -1;
 
+    private int mUserId;
     private List<PackageInfo> mAllPackages;
     private PackageManager mPackageManager;
     // version & signature info of each app in a restore set
@@ -129,17 +129,18 @@
 
     // We're constructed with the set of applications that are participating
     // in backup.  This set changes as apps are installed & removed.
-    public PackageManagerBackupAgent(PackageManager packageMgr, List<PackageInfo> packages) {
-        init(packageMgr, packages);
+    public PackageManagerBackupAgent(
+            PackageManager packageMgr, List<PackageInfo> packages, int userId) {
+        init(packageMgr, packages, userId);
     }
 
-    public PackageManagerBackupAgent(PackageManager packageMgr) {
-        init(packageMgr, null);
+    public PackageManagerBackupAgent(PackageManager packageMgr, int userId) {
+        init(packageMgr, null, userId);
 
         evaluateStorablePackages();
     }
 
-    private void init(PackageManager packageMgr, List<PackageInfo> packages) {
+    private void init(PackageManager packageMgr, List<PackageInfo> packages, int userId) {
         mPackageManager = packageMgr;
         mAllPackages = packages;
         mRestoredSignatures = null;
@@ -147,17 +148,19 @@
 
         mStoredSdkVersion = Build.VERSION.SDK_INT;
         mStoredIncrementalVersion = Build.VERSION.INCREMENTAL;
+        mUserId = userId;
     }
 
     // We will need to refresh our understanding of what is eligible for
     // backup periodically; this entry point serves that purpose.
     public void evaluateStorablePackages() {
-        mAllPackages = getStorableApplications(mPackageManager);
+        mAllPackages = getStorableApplications(mPackageManager, mUserId);
     }
 
-    public static List<PackageInfo> getStorableApplications(PackageManager pm) {
-        List<PackageInfo> pkgs;
-        pkgs = pm.getInstalledPackages(PackageManager.GET_SIGNING_CERTIFICATES);
+    /** Gets all packages installed on user {@code userId} eligible for backup. */
+    public static List<PackageInfo> getStorableApplications(PackageManager pm, int userId) {
+        List<PackageInfo> pkgs =
+                pm.getInstalledPackagesAsUser(PackageManager.GET_SIGNING_CERTIFICATES, userId);
         int N = pkgs.size();
         for (int a = N-1; a >= 0; a--) {
             PackageInfo pkg = pkgs.get(a);
@@ -237,8 +240,8 @@
         ComponentName home = getPreferredHomeComponent();
         if (home != null) {
             try {
-                homeInfo = mPackageManager.getPackageInfo(home.getPackageName(),
-                        PackageManager.GET_SIGNING_CERTIFICATES);
+                homeInfo = mPackageManager.getPackageInfoAsUser(home.getPackageName(),
+                        PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
                 homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
                 homeVersion = homeInfo.getLongVersionCode();
                 SigningInfo signingInfo = homeInfo.signingInfo;
@@ -315,8 +318,8 @@
                 } else {
                     PackageInfo info = null;
                     try {
-                        info = mPackageManager.getPackageInfo(packName,
-                                PackageManager.GET_SIGNING_CERTIFICATES);
+                        info = mPackageManager.getPackageInfoAsUser(packName,
+                                PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
                     } catch (NameNotFoundException e) {
                         // Weird; we just found it, and now are told it doesn't exist.
                         // Treat it as having been removed from the device.
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index ed6a46c..3a8966a 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -249,11 +249,11 @@
     private final TransportManager mTransportManager;
     private final HandlerThread mUserBackupThread;
 
-    private Context mContext;
-    private PackageManager mPackageManager;
-    private IPackageManager mPackageManagerBinder;
-    private IActivityManager mActivityManager;
-    private ActivityManagerInternal mActivityManagerInternal;
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+    private final IPackageManager mPackageManagerBinder;
+    private final IActivityManager mActivityManager;
+    private final ActivityManagerInternal mActivityManagerInternal;
     private PowerManager mPowerManager;
     private final AlarmManager mAlarmManager;
     private final IStorageManager mStorageManager;
@@ -496,11 +496,18 @@
         mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null");
         mBaseStateDir.mkdirs();
         if (!SELinux.restorecon(mBaseStateDir)) {
-            Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+            Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
         }
 
         mDataDir = checkNotNull(dataDir, "dataDir cannot be null");
-
+        // TODO(b/120424138): Remove when the system user moves out of the cache dir. The cache dir
+        // is managed by init.rc so we don't have to create it below.
+        if (userId != UserHandle.USER_SYSTEM) {
+            mDataDir.mkdirs();
+            if (!SELinux.restorecon(mDataDir)) {
+                Slog.w(TAG, "SELinux restorecon failed on " + mDataDir);
+            }
+        }
         mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
 
         // Receivers for scheduled backups and transport initialization operations.
@@ -797,7 +804,7 @@
      * non-lifecycle agent instance, so we manually set up the context topology for it.
      */
     public BackupAgent makeMetadataAgent() {
-        PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
+        PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager, mUserId);
         pmAgent.attach(mContext);
         pmAgent.onCreate();
         return pmAgent;
@@ -808,7 +815,7 @@
      */
     public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) {
         PackageManagerBackupAgent pmAgent =
-                new PackageManagerBackupAgent(mPackageManager, packages);
+                new PackageManagerBackupAgent(mPackageManager, packages, mUserId);
         pmAgent.attach(mContext);
         pmAgent.onCreate();
         return pmAgent;
@@ -879,7 +886,7 @@
         boolean changed = false;
         ArrayList<FullBackupEntry> schedule = null;
         List<PackageInfo> apps =
-                PackageManagerBackupAgent.getStorableApplications(mPackageManager);
+                PackageManagerBackupAgent.getStorableApplications(mPackageManager, mUserId);
 
         if (mFullBackupScheduleFile.exists()) {
             try (FileInputStream fstream = new FileInputStream(mFullBackupScheduleFile);
@@ -1428,8 +1435,7 @@
             mConnecting = true;
             mConnectedAgent = null;
             try {
-                if (mActivityManager.bindBackupAgent(app.packageName, mode,
-                        UserHandle.USER_OWNER)) {
+                if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId)) {
                     Slog.d(TAG, "awaiting agent for " + app);
 
                     // success; wait for the agent to arrive
@@ -1460,11 +1466,7 @@
             }
         }
         if (agent == null) {
-            try {
-                mActivityManager.clearPendingBackup();
-            } catch (RemoteException e) {
-                // can't happen - ActivityManager is local
-            }
+            mActivityManagerInternal.clearPendingBackup(mUserId);
         }
         return agent;
     }
@@ -1488,7 +1490,7 @@
     public void clearApplicationDataSynchronous(String packageName, boolean keepSystemState) {
         // Don't wipe packages marked allowClearUserData=false
         try {
-            PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
+            PackageInfo info = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
             if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) {
                 if (MORE_DEBUG) {
                     Slog.i(TAG, "allowClearUserData=false so not wiping "
@@ -1507,7 +1509,7 @@
             mClearingData = true;
             try {
                 mActivityManager.clearApplicationUserData(
-                        packageName, keepSystemState, observer, 0);
+                        packageName, keepSystemState, observer, mUserId);
             } catch (RemoteException e) {
                 // can't happen because the activity manager is in this process
             }
@@ -1616,8 +1618,8 @@
                 continue;
             }
             try {
-                PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
-                        PackageManager.GET_SIGNING_CERTIFICATES);
+                PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName,
+                        PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
                 if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo,
                         mPackageManager)) {
                     BackupObserverUtils.sendBackupOnPackageResult(observer, packageName,
@@ -2339,8 +2341,8 @@
         if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName);
         PackageInfo info;
         try {
-            info = mPackageManager.getPackageInfo(packageName,
-                    PackageManager.GET_SIGNING_CERTIFICATES);
+            info = mPackageManager.getPackageInfoAsUser(packageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
         } catch (NameNotFoundException e) {
             Slog.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
             return;
@@ -3258,7 +3260,7 @@
             if (packageName != null) {
                 PackageInfo app = null;
                 try {
-                    app = mPackageManager.getPackageInfo(packageName, 0);
+                    app = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
                 } catch (NameNotFoundException nnf) {
                     Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName);
                     throw new IllegalArgumentException("Package " + packageName + " not found");
@@ -3362,7 +3364,7 @@
                     mTransportManager.getCurrentTransportClient(callerLogString);
             boolean eligible =
                     AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
-                            transportClient, packageName, mPackageManager);
+                            transportClient, packageName, mPackageManager, mUserId);
             if (transportClient != null) {
                 mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
             }
@@ -3386,7 +3388,7 @@
             for (String packageName : packages) {
                 if (AppBackupUtils
                         .appIsRunningAndEligibleForBackupWithTransport(
-                                transportClient, packageName, mPackageManager)) {
+                                transportClient, packageName, mPackageManager, mUserId)) {
                     eligibleApps.add(packageName);
                 }
             }
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index ef7ff92..862ca71 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -45,7 +45,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.UserHandle;
 import android.os.WorkSource;
 
 import com.android.internal.annotations.GuardedBy;
@@ -241,6 +240,7 @@
     private final boolean mUserInitiated;
     private final boolean mNonIncremental;
     private final int mCurrentOpToken;
+    private final int mUserId;
     private final File mStateDirectory;
     private final File mDataDirectory;
     private final File mBlankStateFile;
@@ -320,6 +320,7 @@
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
         mQueueLock = mBackupManagerService.getQueueLock();
         mBlankStateFile = new File(mStateDirectory, BLANK_STATE_FILE_NAME);
+        mUserId = backupManagerService.getUserId();
     }
 
     private void registerTask() {
@@ -480,8 +481,8 @@
         final PackageInfo packageInfo;
         try {
             packageInfo =
-                    mPackageManager.getPackageInfo(
-                            packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+                    mPackageManager.getPackageInfoAsUser(
+                            packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
         } catch (PackageManager.NameNotFoundException e) {
             mReporter.onAgentUnknown(packageName);
             throw AgentException.permanent(e);
@@ -770,8 +771,7 @@
 
     private void writeWidgetPayloadIfAppropriate(FileDescriptor fd, String pkgName)
             throws IOException {
-        // TODO: http://b/22388012
-        byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, UserHandle.USER_SYSTEM);
+        byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, mUserId);
         File widgetFile = new File(mStateDirectory, pkgName + "_widget");
         boolean priorStateExists = widgetFile.exists();
         if (!priorStateExists && widgetState == null) {
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index e273b32..0fa0f89 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -54,6 +54,7 @@
     private final TransportManager mTransportManager;
     private final String mTransportName;
     private final UserBackupManagerService mBackupManagerService;
+    private final int mUserId;
     @Nullable private final String mPackageName;
     public RestoreSet[] mRestoreSets = null;
     boolean mEnded = false;
@@ -67,6 +68,7 @@
         mPackageName = packageName;
         mTransportManager = backupManagerService.getTransportManager();
         mTransportName = transportName;
+        mUserId = backupManagerService.getUserId();
     }
 
     public void markTimedOut() {
@@ -304,7 +306,8 @@
 
         final PackageInfo app;
         try {
-            app = mBackupManagerService.getPackageManager().getPackageInfo(packageName, 0);
+            app = mBackupManagerService.getPackageManager().getPackageInfoAsUser(
+                    packageName, 0, mUserId);
         } catch (NameNotFoundException nnf) {
             Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName);
             return -1;
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 45a398f..c7f3315 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -272,7 +272,7 @@
                                         instream, mBackupManagerService.getContext(),
                                         mDeleteObserver, mManifestSignatures,
                                         mPackagePolicies, info, installerPackageName,
-                                        bytesReadListener);
+                                        bytesReadListener, mBackupManagerService.getUserId());
                                 // good to go; promote to ACCEPT
                                 mPackagePolicies.put(pkg, isSuccessfullyInstalled
                                         ? RestorePolicy.ACCEPT
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index f7efad6..5284d94 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -48,7 +48,6 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
 
@@ -81,6 +80,7 @@
 public class PerformUnifiedRestoreTask implements BackupRestoreTask {
 
     private UserBackupManagerService backupManagerService;
+    private final int mUserId;
     private final TransportManager mTransportManager;
     // Transport client we're working with to do the restore
     private final TransportClient mTransportClient;
@@ -175,6 +175,7 @@
             @Nullable String[] filterSet,
             OnTaskFinishedListener listener) {
         this.backupManagerService = backupManagerService;
+        mUserId = backupManagerService.getUserId();
         mTransportManager = backupManagerService.getTransportManager();
         mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
         mState = UnifiedRestoreState.INITIAL;
@@ -204,7 +205,7 @@
                 // We want everything and a pony
                 List<PackageInfo> apps =
                         PackageManagerBackupAgent.getStorableApplications(
-                                backupManagerService.getPackageManager());
+                                backupManagerService.getPackageManager(), mUserId);
                 filterSet = packagesToNames(apps);
                 if (DEBUG) {
                     Slog.i(TAG, "Full restore; asking about " + filterSet.length + " apps");
@@ -221,7 +222,7 @@
             for (int i = 0; i < filterSet.length; i++) {
                 try {
                     PackageManager pm = backupManagerService.getPackageManager();
-                    PackageInfo info = pm.getPackageInfo(filterSet[i], 0);
+                    PackageInfo info = pm.getPackageInfoAsUser(filterSet[i], 0, mUserId);
                     if ("android".equals(info.packageName)) {
                         hasSystem = true;
                         continue;
@@ -240,16 +241,16 @@
             }
             if (hasSystem) {
                 try {
-                    mAcceptSet.add(0,
-                            backupManagerService.getPackageManager().getPackageInfo("android", 0));
+                    mAcceptSet.add(0, backupManagerService.getPackageManager().getPackageInfoAsUser(
+                                    "android", 0, mUserId));
                 } catch (NameNotFoundException e) {
                     // won't happen; we know a priori that it's valid
                 }
             }
             if (hasSettings) {
                 try {
-                    mAcceptSet.add(backupManagerService.getPackageManager().getPackageInfo(
-                            SETTINGS_PACKAGE, 0));
+                    mAcceptSet.add(backupManagerService.getPackageManager().getPackageInfoAsUser(
+                            SETTINGS_PACKAGE, 0, mUserId));
                 } catch (NameNotFoundException e) {
                     // this one is always valid too
                 }
@@ -360,7 +361,7 @@
         // If we're starting a full-system restore, set up to begin widget ID remapping
         if (mIsSystemRestore) {
             // TODO: http://b/22388012
-            AppWidgetBackupBridge.restoreStarting(UserHandle.USER_SYSTEM);
+            AppWidgetBackupBridge.restoreStarting(mUserId);
         }
 
         try {
@@ -508,8 +509,8 @@
             }
 
             try {
-                mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo(
-                        pkgName, PackageManager.GET_SIGNING_CERTIFICATES);
+                mCurrentPackage = backupManagerService.getPackageManager().getPackageInfoAsUser(
+                        pkgName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
             } catch (NameNotFoundException e) {
                 // Whoops, we thought we could restore this package but it
                 // turns out not to be present.  Skip it.
@@ -1079,7 +1080,7 @@
 
         // Kick off any work that may be needed regarding app widget restores
         // TODO: http://b/22388012
-        AppWidgetBackupBridge.restoreFinished(UserHandle.USER_SYSTEM);
+        AppWidgetBackupBridge.restoreFinished(mUserId);
 
         // If this was a full-system restore, record the ancestral
         // dataset information
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 e465c7e..054879b 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -91,10 +91,13 @@
      * </ol>
      */
     public static boolean appIsRunningAndEligibleForBackupWithTransport(
-            @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
+            @Nullable TransportClient transportClient,
+            String packageName,
+            PackageManager pm,
+            int userId) {
         try {
-            PackageInfo packageInfo = pm.getPackageInfo(packageName,
-                    PackageManager.GET_SIGNING_CERTIFICATES);
+            PackageInfo packageInfo = pm.getPackageInfoAsUser(packageName,
+                    PackageManager.GET_SIGNING_CERTIFICATES, userId);
             ApplicationInfo applicationInfo = packageInfo.applicationInfo;
             if (!appIsEligibleForBackup(applicationInfo, pm)
                     || appIsStopped(applicationInfo)
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index df7e6d4..cce5b3b 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -72,7 +72,9 @@
             HashMap<String, Signature[]> manifestSignatures,
             HashMap<String, RestorePolicy> packagePolicies,
             FileMetadata info,
-            String installerPackageName, BytesReadListener bytesReadListener) {
+            String installerPackageName,
+            BytesReadListener bytesReadListener,
+            int userId) {
         boolean okay = true;
 
         if (DEBUG) {
@@ -144,8 +146,8 @@
                     uninstall = true;
                 } else {
                     try {
-                        PackageInfo pkg = packageManager.getPackageInfo(info.packageName,
-                                PackageManager.GET_SIGNING_CERTIFICATES);
+                        PackageInfo pkg = packageManager.getPackageInfoAsUser(info.packageName,
+                                PackageManager.GET_SIGNING_CERTIFICATES, userId);
                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP)
                                 == 0) {
                             Slog.w(TAG, "Restore stream contains apk of package "
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3b08a00..bd6fa49 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -920,8 +920,8 @@
     /**
      * Backup/restore process management
      */
-    String mBackupAppName = null;
-    BackupRecord mBackupTarget = null;
+    @GuardedBy("this")
+    final SparseArray<BackupRecord> mBackupTargets = new SparseArray<>();
 
     final ProviderMap mProviderMap;
 
@@ -4365,6 +4365,7 @@
         mProcessList.removeProcessLocked(app, false, true, "timeout publishing content providers");
     }
 
+    @GuardedBy("this")
     private final void processStartTimedOutLocked(ProcessRecord app) {
         final int pid = app.pid;
         boolean gone = mPidsSelfLocked.removeIfNoThread(pid);
@@ -4385,7 +4386,8 @@
                 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
             }
             removeLruProcessLocked(app);
-            if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
+            final BackupRecord backupTarget = mBackupTargets.get(app.userId);
+            if (backupTarget != null && backupTarget.app.pid == pid) {
                 Slog.w(TAG, "Unattached app died before backup, skipping");
                 mHandler.post(new Runnable() {
                 @Override
@@ -4393,7 +4395,7 @@
                         try {
                             IBackupManager bm = IBackupManager.Stub.asInterface(
                                     ServiceManager.getService(Context.BACKUP_SERVICE));
-                            bm.agentDisconnected(app.info.packageName);
+                            bm.agentDisconnectedForUser(app.userId, app.info.packageName);
                         } catch (RemoteException e) {
                             // Can't happen; the backup manager is local
                         }
@@ -4516,6 +4518,7 @@
         if (DEBUG_ALL) Slog.v(
             TAG, "New app record " + app
             + " thread=" + thread.asBinder() + " pid=" + pid);
+        final BackupRecord backupTarget = mBackupTargets.get(app.userId);
         try {
             int testMode = ApplicationThreadConstants.DEBUG_OFF;
             if (mDebugApp != null && mDebugApp.equals(processName)) {
@@ -4537,11 +4540,11 @@
 
             // If the app is being launched for restore or full backup, set it up specially
             boolean isRestrictedBackupMode = false;
-            if (mBackupTarget != null && mBackupAppName.equals(processName)) {
-                isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID
-                        && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
-                                || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
-                                || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
+            if (backupTarget != null && backupTarget.appInfo.packageName.equals(processName)) {
+                isRestrictedBackupMode = backupTarget.appInfo.uid >= FIRST_APPLICATION_UID
+                        && ((backupTarget.backupMode == BackupRecord.RESTORE)
+                                || (backupTarget.backupMode == BackupRecord.RESTORE_FULL)
+                                || (backupTarget.backupMode == BackupRecord.BACKUP_FULL));
             }
 
             final ActiveInstrumentation instr = app.getActiveInstrumentation();
@@ -4749,15 +4752,15 @@
         }
 
         // Check whether the next backup agent is in this process...
-        if (!badApp && mBackupTarget != null && mBackupTarget.app == app) {
+        if (!badApp && backupTarget != null && backupTarget.app == app) {
             if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
                     "New app is backup target, launching agent for " + app);
-            notifyPackageUse(mBackupTarget.appInfo.packageName,
+            notifyPackageUse(backupTarget.appInfo.packageName,
                              PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
             try {
-                thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
-                        compatibilityInfoForPackage(mBackupTarget.appInfo),
-                        mBackupTarget.backupMode);
+                thread.scheduleCreateBackupAgent(backupTarget.appInfo,
+                        compatibilityInfoForPackage(backupTarget.appInfo),
+                        backupTarget.backupMode);
             } catch (Exception e) {
                 Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
                 badApp = true;
@@ -13224,16 +13227,17 @@
         app.receivers.clear();
 
         // If the app is undergoing backup, tell the backup manager about it
-        if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
+        final BackupRecord backupTarget = mBackupTargets.get(app.userId);
+        if (backupTarget != null && app.pid == backupTarget.app.pid) {
             if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
-                    + mBackupTarget.appInfo + " died during backup");
+                    + backupTarget.appInfo + " died during backup");
             mHandler.post(new Runnable() {
                 @Override
                 public void run(){
                     try {
                         IBackupManager bm = IBackupManager.Stub.asInterface(
                                 ServiceManager.getService(Context.BACKUP_SERVICE));
-                        bm.agentDisconnected(app.info.packageName);
+                        bm.agentDisconnectedForUser(app.userId, app.info.packageName);
                     } catch (RemoteException e) {
                         // can't happen; backup manager is local
                     }
@@ -13573,7 +13577,11 @@
     // instantiated.  The backup agent will invoke backupAgentCreated() on the
     // activity manager to announce its creation.
     public boolean bindBackupAgent(String packageName, int backupMode, int userId) {
-        if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode);
+        if (DEBUG_BACKUP) {
+            Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode="
+                    + backupMode + " userId=" + userId + " callingUid = " + Binder.getCallingUid()
+                    + " uid = " + Process.myUid());
+        }
         enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent");
 
         IPackageManager pm = AppGlobals.getPackageManager();
@@ -13625,10 +13633,10 @@
                 proc.inFullBackup = true;
             }
             r.app = proc;
-            oldBackupUid = mBackupTarget != null ? mBackupTarget.appInfo.uid : -1;
+            final BackupRecord backupTarget = mBackupTargets.get(userId);
+            oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
             newBackupUid = proc.inFullBackup ? r.appInfo.uid : -1;
-            mBackupTarget = r;
-            mBackupAppName = app.packageName;
+            mBackupTargets.put(userId, r);
 
             // Try not to kill the process during backup
             updateOomAdjLocked(proc, true);
@@ -13663,14 +13671,14 @@
         return true;
     }
 
-    @Override
-    public void clearPendingBackup() {
-        if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "clearPendingBackup");
-        enforceCallingPermission("android.permission.BACKUP", "clearPendingBackup");
+    private void clearPendingBackup(int userId) {
+        if (DEBUG_BACKUP) {
+            Slog.v(TAG_BACKUP, "clearPendingBackup: userId = " + userId + " callingUid = "
+                    + Binder.getCallingUid() + " uid = " + Process.myUid());
+        }
 
         synchronized (this) {
-            mBackupTarget = null;
-            mBackupAppName = null;
+            mBackupTargets.delete(userId);
         }
 
         JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
@@ -13678,12 +13686,19 @@
     }
 
     // A backup agent has just come up
+    @Override
     public void backupAgentCreated(String agentPackageName, IBinder agent) {
-        if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName
-                + " = " + agent);
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (DEBUG_BACKUP) {
+            Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
+                    + " callingUserId = " + callingUserId + " callingUid = "
+                    + Binder.getCallingUid() + " uid = " + Process.myUid());
+        }
 
         synchronized(this) {
-            if (!agentPackageName.equals(mBackupAppName)) {
+            final BackupRecord backupTarget = mBackupTargets.get(callingUserId);
+            String backupAppName = backupTarget == null ? null : backupTarget.appInfo.packageName;
+            if (!agentPackageName.equals(backupAppName)) {
                 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
                 return;
             }
@@ -13693,7 +13708,7 @@
         try {
             IBackupManager bm = IBackupManager.Stub.asInterface(
                     ServiceManager.getService(Context.BACKUP_SERVICE));
-            bm.agentConnected(agentPackageName, agent);
+            bm.agentConnectedForUser(callingUserId, agentPackageName, agent);
         } catch (RemoteException e) {
             // can't happen; the backup manager service is local
         } catch (Exception e) {
@@ -13706,7 +13721,12 @@
 
     // done with this agent
     public void unbindBackupAgent(ApplicationInfo appInfo) {
-        if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "unbindBackupAgent: " + appInfo);
+        if (DEBUG_BACKUP) {
+            Slog.v(TAG_BACKUP, "unbindBackupAgent: " + appInfo + " appInfo.uid = "
+                    + appInfo.uid + " callingUid = " + Binder.getCallingUid() + " uid = "
+                    + Process.myUid());
+        }
+
         enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "unbindBackupAgent");
         if (appInfo == null) {
             Slog.w(TAG, "unbind backup agent for null app");
@@ -13715,24 +13735,27 @@
 
         int oldBackupUid;
 
+        final int userId = UserHandle.getUserId(appInfo.uid);
         synchronized(this) {
+            final BackupRecord backupTarget = mBackupTargets.get(userId);
+            String backupAppName = backupTarget == null ? null : backupTarget.appInfo.packageName;
             try {
-                if (mBackupAppName == null) {
+                if (backupAppName == null) {
                     Slog.w(TAG, "Unbinding backup agent with no active backup");
                     return;
                 }
 
-                if (!mBackupAppName.equals(appInfo.packageName)) {
+                if (!backupAppName.equals(appInfo.packageName)) {
                     Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
                     return;
                 }
 
                 // Not backing this app up any more; reset its OOM adjustment
-                final ProcessRecord proc = mBackupTarget.app;
+                final ProcessRecord proc = backupTarget.app;
                 updateOomAdjLocked(proc, true);
                 proc.inFullBackup = false;
 
-                oldBackupUid = mBackupTarget != null ? mBackupTarget.appInfo.uid : -1;
+                oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
 
                 // If the app crashed during backup, 'thread' will be null here
                 if (proc.thread != null) {
@@ -13745,8 +13768,7 @@
                     }
                 }
             } finally {
-                mBackupTarget = null;
-                mBackupAppName = null;
+                mBackupTargets.delete(userId);
             }
         }
 
@@ -17771,6 +17793,11 @@
         public boolean isAppForeground(int uid) {
             return ActivityManagerService.this.isAppForeground(uid);
         }
+
+        @Override
+        public void clearPendingBackup(int userId) {
+            ActivityManagerService.this.clearPendingBackup(userId);
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index cb4cac9..1f9362e 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1024,7 +1024,8 @@
         app.hasStartedServices = false;
         app.adjSeq = mAdjSeq;
 
-        if (mService.mBackupTarget != null && app == mService.mBackupTarget.app) {
+        final BackupRecord backupTarget = mService.mBackupTargets.get(app.userId);
+        if (backupTarget != null && app == backupTarget.app) {
             // If possible we want to avoid killing apps while they're being backed up
             if (adj > ProcessList.BACKUP_APP_ADJ) {
                 if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app);
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 8d7811f..714a807 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -1454,8 +1454,8 @@
                 if (accessCount > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsManager.uidStateToString(uidState));
-                        mWriter.print("[");
+                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(" = ");
                         printedUidState = true;
                     }
                     mWriter.print("access=");
@@ -1465,11 +1465,11 @@
                 if (rejectCount > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsManager.uidStateToString(uidState));
-                        mWriter.print("[");
+                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(" = ");
                         printedUidState = true;
                     } else {
-                        mWriter.print(",");
+                        mWriter.print(", ");
                     }
                     mWriter.print("reject=");
                     mWriter.print(rejectCount);
@@ -1478,16 +1478,17 @@
                 if (accessDuration > 0) {
                     if (!printedUidState) {
                         mWriter.print(mUidStatePrefix);
-                        mWriter.print(AppOpsManager.uidStateToString(uidState));
+                        mWriter.print(AppOpsService.UID_STATE_NAMES[uidState]);
+                        mWriter.print(" = ");
                         printedUidState = true;
                     } else {
-                        mWriter.print(",");
+                        mWriter.print(", ");
                     }
                     mWriter.print("duration=");
-                    mWriter.print(accessDuration);
+                    TimeUtils.formatDuration(accessDuration, mWriter);
                 }
                 if (printedUidState) {
-                    mWriter.println("]");
+                    mWriter.println("");
                 }
             }
         }
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index b332c47..2fe17d8 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -34,8 +34,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.display.ColorDisplayManager;
+import android.graphics.ColorSpace;
 import android.hardware.display.IColorDisplayManager;
 import android.net.Uri;
 import android.opengl.Matrix;
@@ -59,6 +61,7 @@
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
 
+import java.io.PrintWriter;
 import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalDateTime;
@@ -148,26 +151,204 @@
     };
 
     private final TintController mDisplayWhiteBalanceTintController = new TintController() {
+        // Three chromaticity coordinates per color: X, Y, and Z
+        private final int NUM_VALUES_PER_PRIMARY = 3;
+        // Four colors: red, green, blue, and white
+        private final int NUM_DISPLAY_PRIMARIES_VALS = 4 * NUM_VALUES_PER_PRIMARY;
 
+        private final Object mLock = new Object();
+        private int mTemperatureMin;
+        private int mTemperatureMax;
+        private int mTemperatureDefault;
+        private float[] mDisplayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+        private ColorSpace.Rgb mDisplayColorSpaceRGB;
+        private float[] mChromaticAdaptationMatrix;
+        private int mCurrentColorTemperature;
+        private float[] mCurrentColorTemperatureXYZ;
+        private boolean mSetUp = false;
         private float[] mMatrixDisplayWhiteBalance = new float[16];
 
         @Override
         public void setUp(Context context, boolean needsLinear) {
+            mSetUp = false;
+
+            final Resources res = getContext().getResources();
+            final String[] displayPrimariesValues = res.getStringArray(
+                    R.array.config_displayWhiteBalanceDisplayPrimaries);
+            final String[] nominalWhiteValues = res.getStringArray(
+                    R.array.config_displayWhiteBalanceDisplayNominalWhite);
+
+            if (displayPrimariesValues.length != NUM_DISPLAY_PRIMARIES_VALS) {
+                Slog.e(TAG, "Unexpected display white balance primaries resource length " +
+                        displayPrimariesValues.length);
+                return;
+            }
+
+            if (nominalWhiteValues.length != NUM_VALUES_PER_PRIMARY) {
+                Slog.e(TAG, "Unexpected display white balance nominal white resource length " +
+                        nominalWhiteValues.length);
+                return;
+            }
+
+            float[] displayRedGreenBlueXYZ =
+                new float[NUM_DISPLAY_PRIMARIES_VALS - NUM_VALUES_PER_PRIMARY];
+            float[] displayWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+            for (int i = 0; i < displayRedGreenBlueXYZ.length; i++) {
+                displayRedGreenBlueXYZ[i] = Float.parseFloat(displayPrimariesValues[i]);
+            }
+            for (int i = 0; i < displayWhiteXYZ.length; i++) {
+                displayWhiteXYZ[i] = Float.parseFloat(
+                        displayPrimariesValues[displayRedGreenBlueXYZ.length + i]);
+            }
+
+            final ColorSpace.Rgb displayColorSpaceRGB = new ColorSpace.Rgb(
+                "Display Color Space",
+                displayRedGreenBlueXYZ,
+                displayWhiteXYZ,
+                2.2f // gamma, unused for display white balance
+            );
+
+            float[] displayNominalWhiteXYZ = new float[NUM_VALUES_PER_PRIMARY];
+            for (int i = 0; i < nominalWhiteValues.length; i++) {
+                displayNominalWhiteXYZ[i] = Float.parseFloat(nominalWhiteValues[i]);
+            }
+
+            final int colorTemperatureMin = res.getInteger(
+                    R.integer.config_displayWhiteBalanceColorTemperatureMin);
+            if (colorTemperatureMin <= 0) {
+                Slog.e(TAG, "display white balance minimum temperature must be greater than 0");
+                return;
+            }
+
+            final int colorTemperatureMax = res.getInteger(
+                    R.integer.config_displayWhiteBalanceColorTemperatureMax);
+            if (colorTemperatureMax < colorTemperatureMin) {
+                Slog.e(TAG, "display white balance max temp must be greater or equal to min");
+                return;
+            }
+
+            final int colorTemperature = res.getInteger(
+                    R.integer.config_displayWhiteBalanceColorTemperatureDefault);
+
+            synchronized (mLock) {
+                mDisplayColorSpaceRGB = displayColorSpaceRGB;
+                mDisplayNominalWhiteXYZ = displayNominalWhiteXYZ;
+                mTemperatureMin = colorTemperatureMin;
+                mTemperatureMax = colorTemperatureMax;
+                mTemperatureDefault = colorTemperature;
+                mSetUp = true;
+            }
+
+            setMatrix(mTemperatureDefault);
         }
 
         @Override
         public float[] getMatrix() {
-            return isActivated() ? mMatrixDisplayWhiteBalance : MATRIX_IDENTITY;
+            return mSetUp && isActivated() ? mMatrixDisplayWhiteBalance : MATRIX_IDENTITY;
         }
 
         @Override
         public void setMatrix(int cct) {
+            if (!mSetUp) {
+                Slog.w(TAG, "Can't set display white balance temperature: uninitialized");
+                return;
+            }
+
+            if (cct < mTemperatureMin) {
+                Slog.w(TAG, "Requested display color temperature is below allowed minimum");
+                cct = mTemperatureMin;
+            } else if (cct > mTemperatureMax) {
+                Slog.w(TAG, "Requested display color temperature is above allowed maximum");
+                cct = mTemperatureMax;
+            }
+
+            Slog.d(TAG, "setDisplayWhiteBalanceTemperatureMatrix: cct = " + cct);
+
+            synchronized (mLock) {
+                mCurrentColorTemperature = cct;
+
+                // Adapt the display's nominal white point to match the requested CCT value
+                mCurrentColorTemperatureXYZ = ColorSpace.cctToIlluminantdXyz(cct);
+
+                mChromaticAdaptationMatrix =
+                    ColorSpace.chromaticAdaptation(ColorSpace.Adaptation.BRADFORD,
+                            mDisplayNominalWhiteXYZ, mCurrentColorTemperatureXYZ);
+
+                // Convert the adaptation matrix to RGB space
+                float[] result = ColorSpace.mul3x3(mChromaticAdaptationMatrix,
+                        mDisplayColorSpaceRGB.getTransform());
+                result = ColorSpace.mul3x3(mDisplayColorSpaceRGB.getInverseTransform(), result);
+
+                // Normalize the transform matrix to peak white value in RGB space
+                final float adaptedMaxR = result[0] + result[3] + result[6];
+                final float adaptedMaxG = result[1] + result[4] + result[7];
+                final float adaptedMaxB = result[2] + result[5] + result[8];
+                final float denum = Math.max(Math.max(adaptedMaxR, adaptedMaxG), adaptedMaxB);
+                for (int i = 0; i < result.length; i++) {
+                    result[i] /= denum;
+                }
+
+                Matrix.setIdentityM(mMatrixDisplayWhiteBalance, 0);
+                java.lang.System.arraycopy(result, 0, mMatrixDisplayWhiteBalance, 0, 3);
+                java.lang.System.arraycopy(result, 3, mMatrixDisplayWhiteBalance, 4, 3);
+                java.lang.System.arraycopy(result, 6, mMatrixDisplayWhiteBalance, 8, 3);
+            }
         }
 
         @Override
         public int getLevel() {
             return LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
         }
+
+        /**
+         * Format a given matrix into a string.
+         *
+         * @param matrix the matrix to format
+         * @param cols number of columns in the matrix
+         */
+        private String matrixToString(float[] matrix, int cols) {
+            if (matrix == null || cols <= 0) {
+                Slog.e(TAG, "Invalid arguments when formatting matrix to string");
+                return "";
+            }
+
+            StringBuilder sb = new StringBuilder("");
+            for (int i = 0; i < matrix.length; i++) {
+                if (i % cols == 0) {
+                    sb.append("\n    ");
+                }
+                sb.append(String.format("%9.6f ", matrix[i]));
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public void dump(PrintWriter pw) {
+            synchronized (mLock) {
+                pw.println("ColorDisplayService");
+                pw.println("  mSetUp = " + mSetUp);
+
+                if (!mSetUp) {
+                    return;
+                }
+
+                pw.println("  isActivated = " + isActivated());
+                pw.println("  mTemperatureMin = " + mTemperatureMin);
+                pw.println("  mTemperatureMax = " + mTemperatureMax);
+                pw.println("  mTemperatureDefault = " + mTemperatureDefault);
+                pw.println("  mCurrentColorTemperature = " + mCurrentColorTemperature);
+                pw.println("  mCurrentColorTemperatureXYZ = " +
+                        matrixToString(mCurrentColorTemperatureXYZ, 3));
+                pw.println("  mDisplayColorSpaceRGB RGB-to-XYZ = " +
+                        matrixToString(mDisplayColorSpaceRGB.getTransform(), 3));
+                pw.println("  mChromaticAdaptationMatrix = " +
+                        matrixToString(mChromaticAdaptationMatrix, 3));
+                pw.println("  mDisplayColorSpaceRGB XYZ-to-RGB = " +
+                        matrixToString(mDisplayColorSpaceRGB.getInverseTransform(), 3));
+                pw.println("  mMatrixDisplayWhiteBalance = " +
+                        matrixToString(mMatrixDisplayWhiteBalance, 4));
+            }
+        }
     };
 
     private final TintController mGlobalSaturationTintController = new TintController() {
@@ -230,8 +411,6 @@
 
     private NightDisplayAutoMode mNightDisplayAutoMode;
 
-    private Integer mDisplayWhiteBalanceColorTemperature;
-
     public ColorDisplayService(Context context) {
         super(context);
         mHandler = new TintHandler(Looper.getMainLooper());
@@ -363,7 +542,7 @@
                                 onAccessibilityTransformChanged();
                                 break;
                             case Secure.DISPLAY_WHITE_BALANCE_ENABLED:
-                                onDisplayWhiteBalanceEnabled(isDisplayWhiteBalanceSettingEnabled());
+                                updateDisplayWhiteBalanceStatus();
                                 break;
                         }
                     }
@@ -416,14 +595,9 @@
 
         if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) {
             // Prepare the display white balance transform matrix.
-            mDisplayWhiteBalanceTintController
-                    .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
-            if (mDisplayWhiteBalanceColorTemperature != null) {
-                mDisplayWhiteBalanceTintController
-                        .setMatrix(mDisplayWhiteBalanceColorTemperature);
-            }
+            mDisplayWhiteBalanceTintController.setUp(getContext(), true /* needsLinear */);
 
-            onDisplayWhiteBalanceEnabled(isDisplayWhiteBalanceSettingEnabled());
+            updateDisplayWhiteBalanceStatus();
         }
     }
 
@@ -460,6 +634,8 @@
                 mNightDisplayAutoMode.onActivated(activated);
             }
 
+            updateDisplayWhiteBalanceStatus();
+
             applyTint(mNightDisplayTintController, false);
         }
     }
@@ -516,11 +692,7 @@
                 .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
         mNightDisplayTintController.setMatrix(mNightDisplayController.getColorTemperature());
 
-        mDisplayWhiteBalanceTintController
-                .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
-        if (mDisplayWhiteBalanceColorTemperature != null) {
-            mDisplayWhiteBalanceTintController.setMatrix(mDisplayWhiteBalanceColorTemperature);
-        }
+        updateDisplayWhiteBalanceStatus();
 
         final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
         dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
@@ -611,10 +783,15 @@
         return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt;
     }
 
-    private void onDisplayWhiteBalanceEnabled(boolean enabled) {
-        mDisplayWhiteBalanceTintController.setActivated(enabled);
-        if (mDisplayWhiteBalanceListener != null) {
-            mDisplayWhiteBalanceListener.onDisplayWhiteBalanceStatusChanged(enabled);
+    private void updateDisplayWhiteBalanceStatus() {
+        boolean oldActivated = mDisplayWhiteBalanceTintController.isActivated();
+        mDisplayWhiteBalanceTintController.setActivated(isDisplayWhiteBalanceSettingEnabled() &&
+                !mNightDisplayTintController.isActivated() &&
+                DisplayTransformManager.needsLinearColorMatrix());
+        boolean activated = mDisplayWhiteBalanceTintController.isActivated();
+
+        if (mDisplayWhiteBalanceListener != null && oldActivated != activated) {
+            mDisplayWhiteBalanceListener.onDisplayWhiteBalanceStatusChanged(activated);
         }
     }
 
@@ -896,6 +1073,12 @@
         }
 
         /**
+         * Dump debug information.
+         */
+        public void dump(PrintWriter pw) {
+        }
+
+        /**
          * Set up any constants needed for computing the matrix.
          */
         public abstract void setUp(Context context, boolean needsLinear);
@@ -929,11 +1112,10 @@
          */
         public boolean setDisplayWhiteBalanceColorTemperature(int cct) {
             // Update the transform matrix even if it can't be applied.
-            mDisplayWhiteBalanceColorTemperature = cct;
             mDisplayWhiteBalanceTintController.setMatrix(cct);
 
             if (mDisplayWhiteBalanceTintController.isActivated()) {
-                applyTint(mDisplayWhiteBalanceTintController, true);
+                applyTint(mDisplayWhiteBalanceTintController, false);
                 return true;
             }
             return false;
@@ -946,6 +1128,10 @@
             mDisplayWhiteBalanceListener = listener;
             return mDisplayWhiteBalanceTintController.isActivated();
         }
+
+        public void dump(PrintWriter pw) {
+            mDisplayWhiteBalanceTintController.dump(pw);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 4a17c65..2340b77 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -95,6 +95,7 @@
 import com.android.server.UiThread;
 import com.android.server.wm.SurfaceAnimationThread;
 import com.android.server.wm.WindowManagerInternal;
+import com.android.server.display.ColorDisplayService.ColorDisplayServiceInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -1459,6 +1460,13 @@
 
             pw.println();
             mPersistentDataStore.dump(pw);
+
+            final ColorDisplayServiceInternal cds = LocalServices.getService(
+                    ColorDisplayServiceInternal.class);
+            if (cds != null) {
+                pw.println();
+                cds.dump(pw);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 5fa3f52..7ff6a2f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -89,6 +89,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.provider.Settings;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
@@ -309,6 +310,7 @@
     private final HardKeyboardListener mHardKeyboardListener;
     private final AppOpsManager mAppOpsManager;
     private final UserManager mUserManager;
+    private final UserManagerInternal mUserManagerInternal;
 
     // All known input methods.  mMethodMap also serves as the global
     // lock for this class.
@@ -1405,6 +1407,7 @@
         }, true /*asyncHandler*/);
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mUserManager = mContext.getSystemService(UserManager.class);
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
         mHardKeyboardListener = new HardKeyboardListener();
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_INPUT_METHODS);
@@ -1489,7 +1492,7 @@
         // If the system is not ready or the device is not yed unlocked by the user, then we use
         // copy-on-write settings.
         final boolean useCopyOnWriteSettings =
-                !mSystemReady || !mUserManager.isUserUnlockingOrUnlocked(newUserId);
+                !mSystemReady || !mUserManagerInternal.isUserUnlockingOrUnlocked(newUserId);
         mSettings.switchCurrentUser(newUserId, useCopyOnWriteSettings);
         updateCurrentProfileIds();
         // Additional subtypes should be reset when the user is changed
@@ -1562,7 +1565,7 @@
                 mLastSystemLocales = mRes.getConfiguration().getLocales();
                 final int currentUserId = mSettings.getCurrentUserId();
                 mSettings.switchCurrentUser(currentUserId,
-                        !mUserManager.isUserUnlockingOrUnlocked(currentUserId));
+                        !mUserManagerInternal.isUserUnlockingOrUnlocked(currentUserId));
                 mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
                 mNotificationManager = mContext.getSystemService(NotificationManager.class);
                 mStatusBar = statusBar;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index eb3017d..b6dae19 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -304,6 +304,17 @@
         }
 
         @Override
+        public boolean shouldHideFromSuggestions(String packageName, UserHandle user) {
+            if (!canAccessProfile(user.getIdentifier(), "cannot get shouldHideFromSuggestions")) {
+                return false;
+            }
+            final PackageManagerInternal pmi = LocalServices.getService(
+                    PackageManagerInternal.class);
+            int flags = pmi.getDistractingPackageRestrictions(packageName, user.getIdentifier());
+            return (flags & PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS) != 0;
+        }
+
+        @Override
         public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
                 String packageName, UserHandle user) throws RemoteException {
             ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 597f5b3..945d7ad 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -84,6 +84,7 @@
 import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.RESTRICTION_NONE;
 import static android.content.pm.PackageParser.isApkFile;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
@@ -12657,22 +12658,30 @@
         info.sendPackageRemovedBroadcasts(true /*killApp*/);
     }
 
+    private void sendDistractingPackagesChanged(String[] pkgList, int[] uidList, int userId,
+            int distractionFlags) {
+        final Bundle extras = new Bundle(3);
+        extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+        extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
+        extras.putInt(Intent.EXTRA_DISTRACTION_RESTRICTIONS, distractionFlags);
+        sendPackageBroadcast(Intent.ACTION_DISTRACTING_PACKAGES_CHANGED, null, extras,
+                Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null, new int[]{userId}, null);
+    }
+
     private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
             boolean suspended, PersistableBundle launcherExtras) {
-        if (pkgList.length > 0) {
-            Bundle extras = new Bundle(1);
-            extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
-            extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
-            if (launcherExtras != null) {
-                extras.putBundle(Intent.EXTRA_LAUNCHER_EXTRAS,
-                        new Bundle(launcherExtras.deepCopy()));
-            }
-            sendPackageBroadcast(
-                    suspended ? Intent.ACTION_PACKAGES_SUSPENDED
-                            : Intent.ACTION_PACKAGES_UNSUSPENDED,
-                    null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null,
-                    new int[] {userId}, null);
+        final Bundle extras = new Bundle(3);
+        extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+        extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
+        if (launcherExtras != null) {
+            extras.putBundle(Intent.EXTRA_LAUNCHER_EXTRAS,
+                    new Bundle(launcherExtras.deepCopy()));
         }
+        sendPackageBroadcast(
+                suspended ? Intent.ACTION_PACKAGES_SUSPENDED
+                        : Intent.ACTION_PACKAGES_UNSUSPENDED,
+                null, extras, Intent.FLAG_RECEIVER_REGISTERED_ONLY, null, null,
+                new int[] {userId}, null);
     }
 
     /**
@@ -12822,6 +12831,62 @@
     }
 
     @Override
+    public String[] setDistractingPackageRestrictionsAsUser(String[] packageNames,
+            int restrictionFlags, int userId) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
+                "setPackagesSuspendedAsUser");
+
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
+                && UserHandle.getUserId(callingUid) != userId) {
+            throw new SecurityException("Calling uid " + callingUid + " cannot call for user "
+                    + userId);
+        }
+        Preconditions.checkNotNull(packageNames, "packageNames cannot be null");
+
+        final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
+        final IntArray changedUids = new IntArray(packageNames.length);
+        final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
+
+        for (int i = 0; i < packageNames.length; i++) {
+            final String packageName = packageNames[i];
+            final PackageSetting pkgSetting;
+            synchronized (mPackages) {
+                pkgSetting = mSettings.mPackages.get(packageName);
+                if (pkgSetting == null || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
+                    Slog.w(TAG, "Could not find package setting for package: " + packageName
+                            + ". Skipping...");
+                    unactionedPackages.add(packageName);
+                    continue;
+                }
+            }
+            if (restrictionFlags != 0 && !canSuspendPackageForUserInternal(packageName, userId)) {
+                unactionedPackages.add(packageName);
+                continue;
+            }
+            synchronized (mPackages) {
+                final int oldDistractionFlags = pkgSetting.getDistractionFlags(userId);
+                if (restrictionFlags != oldDistractionFlags) {
+                    pkgSetting.setDistractionFlags(restrictionFlags, userId);
+                    changedPackagesList.add(packageName);
+                    changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
+                }
+            }
+        }
+
+        if (!changedPackagesList.isEmpty()) {
+            final String[] changedPackages = changedPackagesList.toArray(
+                    new String[changedPackagesList.size()]);
+            sendDistractingPackagesChanged(changedPackages, changedUids.toArray(), userId,
+                    restrictionFlags);
+            synchronized (mPackages) {
+                scheduleWritePackageRestrictionsLocked(userId);
+            }
+        }
+        return unactionedPackages.toArray(new String[0]);
+    }
+
+    @Override
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
             PersistableBundle appExtras, PersistableBundle launcherExtras,
             SuspendDialogInfo dialogInfo, String callingPackage, int userId) {
@@ -12846,44 +12911,37 @@
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
         final IntArray changedUids = new IntArray(packageNames.length);
         final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
-        final long callingId = Binder.clearCallingIdentity();
-        try {
-            for (int i = 0; i < packageNames.length; i++) {
-                final String packageName = packageNames[i];
-                if (callingPackage.equals(packageName)) {
-                    Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
-                            + (suspended ? "" : "un") + "suspend itself. Ignoring");
-                    unactionedPackages.add(packageName);
-                    continue;
-                }
-                PackageSetting pkgSetting;
-                synchronized (mPackages) {
-                    pkgSetting = mSettings.mPackages.get(packageName);
-                    if (pkgSetting == null
-                            || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
-                        Slog.w(TAG, "Could not find package setting for package: " + packageName
-                                + ". Skipping suspending/un-suspending.");
-                        unactionedPackages.add(packageName);
-                        continue;
-                    }
-                }
-                if (suspended && !canSuspendPackageForUserInternal(packageName, userId)) {
-                    unactionedPackages.add(packageName);
-                    continue;
-                }
-                synchronized (mPackages) {
-                    pkgSetting = mSettings.mPackages.get(packageName);
-                    if (pkgSetting != null) {
-                        pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras,
-                                launcherExtras, userId);
-                    }
-                }
-                changedPackagesList.add(packageName);
-                changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
+
+        for (int i = 0; i < packageNames.length; i++) {
+            final String packageName = packageNames[i];
+            if (callingPackage.equals(packageName)) {
+                Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
+                        + (suspended ? "" : "un") + "suspend itself. Ignoring");
+                unactionedPackages.add(packageName);
+                continue;
             }
-        } finally {
-            Binder.restoreCallingIdentity(callingId);
+            final PackageSetting pkgSetting;
+            synchronized (mPackages) {
+                pkgSetting = mSettings.mPackages.get(packageName);
+                if (pkgSetting == null || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
+                    Slog.w(TAG, "Could not find package setting for package: " + packageName
+                            + ". Skipping suspending/un-suspending.");
+                    unactionedPackages.add(packageName);
+                    continue;
+                }
+            }
+            if (suspended && !canSuspendPackageForUserInternal(packageName, userId)) {
+                unactionedPackages.add(packageName);
+                continue;
+            }
+            synchronized (mPackages) {
+                pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras,
+                        launcherExtras, userId);
+            }
+            changedPackagesList.add(packageName);
+            changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
         }
+
         if (!changedPackagesList.isEmpty()) {
             final String[] changedPackages = changedPackagesList.toArray(
                     new String[changedPackagesList.size()]);
@@ -13035,88 +13093,87 @@
                     + " cannot query getUnsuspendablePackagesForUser for user " + userId);
         }
         final ArraySet<String> unactionablePackages = new ArraySet<>();
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            for (String packageName : packageNames) {
-                if (!canSuspendPackageForUserInternal(packageName, userId)) {
-                    unactionablePackages.add(packageName);
-                }
+        for (String packageName : packageNames) {
+            if (!canSuspendPackageForUserInternal(packageName, userId)) {
+                unactionablePackages.add(packageName);
             }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
         }
         return unactionablePackages.toArray(new String[unactionablePackages.size()]);
     }
 
     private boolean canSuspendPackageForUserInternal(String packageName, int userId) {
-        if (isPackageDeviceAdmin(packageName, userId)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": has an active device admin");
-            return false;
-        }
-
-        String activeLauncherPackageName = getActiveLauncherPackageName(userId);
-        if (packageName.equals(activeLauncherPackageName)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": contains the active launcher");
-            return false;
-        }
-
-        if (packageName.equals(mRequiredInstallerPackage)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": required for package installation");
-            return false;
-        }
-
-        if (packageName.equals(mRequiredUninstallerPackage)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": required for package uninstallation");
-            return false;
-        }
-
-        if (packageName.equals(mRequiredVerifierPackage)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": required for package verification");
-            return false;
-        }
-
-        if (packageName.equals(getDefaultDialerPackageName(userId))) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": is the default dialer");
-            return false;
-        }
-
-        if (packageName.equals(mRequiredPermissionControllerPackage)) {
-            Slog.w(TAG, "Cannot suspend package \"" + packageName
-                    + "\": required for permissions management");
-            return false;
-        }
-
-        synchronized (mPackages) {
-            if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            if (isPackageDeviceAdmin(packageName, userId)) {
                 Slog.w(TAG, "Cannot suspend package \"" + packageName
-                        + "\": protected package");
+                        + "\": has an active device admin");
                 return false;
             }
 
-            // Cannot suspend static shared libs as they are considered
-            // a part of the using app (emulating static linking). Also
-            // static libs are installed always on internal storage.
-            PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) {
-                Slog.w(TAG, "Cannot suspend package: " + packageName
-                        + " providing static shared library: "
-                        + pkg.staticSharedLibName);
+            String activeLauncherPackageName = getActiveLauncherPackageName(userId);
+            if (packageName.equals(activeLauncherPackageName)) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": contains the active launcher");
                 return false;
             }
-        }
 
-        if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
-            Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
-            return false;
-        }
+            if (packageName.equals(mRequiredInstallerPackage)) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": required for package installation");
+                return false;
+            }
 
-        return true;
+            if (packageName.equals(mRequiredUninstallerPackage)) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": required for package uninstallation");
+                return false;
+            }
+
+            if (packageName.equals(mRequiredVerifierPackage)) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": required for package verification");
+                return false;
+            }
+
+            if (packageName.equals(getDefaultDialerPackageName(userId))) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": is the default dialer");
+                return false;
+            }
+
+            if (packageName.equals(mRequiredPermissionControllerPackage)) {
+                Slog.w(TAG, "Cannot suspend package \"" + packageName
+                        + "\": required for permissions management");
+                return false;
+            }
+
+            synchronized (mPackages) {
+                if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+                    Slog.w(TAG, "Cannot suspend package \"" + packageName
+                            + "\": protected package");
+                    return false;
+                }
+
+                // Cannot suspend static shared libs as they are considered
+                // a part of the using app (emulating static linking). Also
+                // static libs are installed always on internal storage.
+                PackageParser.Package pkg = mPackages.get(packageName);
+                if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) {
+                    Slog.w(TAG, "Cannot suspend package: " + packageName
+                            + " providing static shared library: "
+                            + pkg.staticSharedLibName);
+                    return false;
+                }
+            }
+
+            if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
+                Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
+                return false;
+            }
+            return true;
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
     }
 
     private String getActiveLauncherPackageName(int userId) {
@@ -13717,14 +13774,15 @@
             IBackupManager bm = IBackupManager.Stub.asInterface(
                     ServiceManager.getService(Context.BACKUP_SERVICE));
             if (bm != null) {
+                int userId = args.user.getIdentifier();
                 if (DEBUG_INSTALL) {
-                    Log.v(TAG, "token " + token + " to BM for possible restore");
+                    Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId);
                 }
                 Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
                 try {
-                    // TODO: http://b/22388012
-                    if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
-                        bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
+                    if (bm.isBackupServiceActive(userId)) {
+                        bm.restoreAtInstallForUser(
+                                userId, res.pkg.applicationInfo.packageName, token);
                     } else {
                         doRestore = false;
                     }
@@ -18425,6 +18483,7 @@
                     true /*stopped*/,
                     true /*notLaunched*/,
                     false /*hidden*/,
+                    0 /*distractionFlags*/,
                     false /*suspended*/,
                     null /*suspendingPackage*/,
                     null /*dialogInfo*/,
@@ -23240,6 +23299,14 @@
         }
 
         @Override
+        public int getDistractingPackageRestrictions(String packageName, int userId) {
+            synchronized (mPackages) {
+                final PackageSetting ps = mSettings.mPackages.get(packageName);
+                return (ps != null) ? ps.getDistractionFlags(userId) : RESTRICTION_NONE;
+            }
+        }
+
+        @Override
         public int getPackageUid(String packageName, int flags, int userId) {
             return PackageManagerService.this
                     .getPackageUid(packageName, flags, userId);
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 3c22f07..58f262c 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -392,6 +392,14 @@
         modifyUserState(userId).hidden = hidden;
     }
 
+    int getDistractionFlags(int userId) {
+        return readUserState(userId).distractionFlags;
+    }
+
+    void setDistractionFlags(int distractionFlags, int userId) {
+        modifyUserState(userId).distractionFlags = distractionFlags;
+    }
+
     boolean getSuspended(int userId) {
         return readUserState(userId).suspended;
     }
@@ -423,7 +431,8 @@
     }
 
     void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
-            boolean notLaunched, boolean hidden, boolean suspended, String suspendingPackage,
+            boolean notLaunched, boolean hidden, int distractionFlags, boolean suspended,
+            String suspendingPackage,
             SuspendDialogInfo dialogInfo, PersistableBundle suspendedAppExtras,
             PersistableBundle suspendedLauncherExtras, boolean instantApp,
             boolean virtualPreload, String lastDisableAppCaller,
@@ -437,6 +446,7 @@
         state.stopped = stopped;
         state.notLaunched = notLaunched;
         state.hidden = hidden;
+        state.distractionFlags = distractionFlags;
         state.suspended = suspended;
         state.suspendingPackage = suspendingPackage;
         state.dialogInfo = dialogInfo;
@@ -607,6 +617,7 @@
             }
             proto.write(PackageProto.UserInfoProto.INSTALL_TYPE, installType);
             proto.write(PackageProto.UserInfoProto.IS_HIDDEN, state.hidden);
+            proto.write(PackageProto.UserInfoProto.DISTRACTION_FLAGS, state.distractionFlags);
             proto.write(PackageProto.UserInfoProto.IS_SUSPENDED, state.suspended);
             if (state.suspended) {
                 proto.write(PackageProto.UserInfoProto.SUSPENDING_PACKAGE, state.suspendingPackage);
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c524dba..95da209 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -223,6 +223,7 @@
     private static final String ATTR_BLOCKED = "blocked";
     // New name for the above attribute.
     private static final String ATTR_HIDDEN = "hidden";
+    private static final String ATTR_DISTRACTION_FLAGS = "distraction_flags";
     private static final String ATTR_SUSPENDED = "suspended";
     private static final String ATTR_SUSPENDING_PACKAGE = "suspending-package";
     /**
@@ -734,6 +735,7 @@
                                 true /*stopped*/,
                                 true /*notLaunched*/,
                                 false /*hidden*/,
+                                0 /*distractionFlags*/,
                                 false /*suspended*/,
                                 null /*suspendingPackage*/,
                                 null /*dialogInfo*/,
@@ -1628,6 +1630,7 @@
                                 false /*stopped*/,
                                 false /*notLaunched*/,
                                 false /*hidden*/,
+                                0 /*distractionFlags*/,
                                 false /*suspended*/,
                                 null /*suspendingPackage*/,
                                 null /*dialogInfo*/,
@@ -1703,6 +1706,8 @@
                     hidden = hiddenStr == null
                             ? hidden : Boolean.parseBoolean(hiddenStr);
 
+                    final int distractionFlags = XmlUtils.readIntAttribute(parser,
+                            ATTR_DISTRACTION_FLAGS, 0);
                     final boolean suspended = XmlUtils.readBooleanAttribute(parser, ATTR_SUSPENDED,
                             false);
                     String suspendingPackage = parser.getAttributeValue(null,
@@ -1781,7 +1786,8 @@
                         setBlockUninstallLPw(userId, name, true);
                     }
                     ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
-                            hidden, suspended, suspendingPackage, suspendDialogInfo,
+                            hidden, distractionFlags, suspended, suspendingPackage,
+                            suspendDialogInfo,
                             suspendedAppExtras, suspendedLauncherExtras, instantApp, virtualPreload,
                             enabledCaller, enabledComponents, disabledComponents, verifState,
                             linkGeneration, installReason, harmfulAppWarning);
@@ -2089,6 +2095,10 @@
                 if (ustate.hidden) {
                     serializer.attribute(null, ATTR_HIDDEN, "true");
                 }
+                if (ustate.distractionFlags != 0) {
+                    serializer.attribute(null, ATTR_DISTRACTION_FLAGS,
+                            Integer.toString(ustate.distractionFlags));
+                }
                 if (ustate.suspended) {
                     serializer.attribute(null, ATTR_SUSPENDED, "true");
                     if (ustate.suspendingPackage != null) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index ac05ee8..bd14223 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -130,7 +130,7 @@
                 ServiceManager.getService("apexservice"));
         boolean success;
         try {
-            success = apex.submitStagedSession(sessionId, apexInfoList);
+            success = apex.submitStagedSession(sessionId, new int[0], apexInfoList);
         } catch (RemoteException re) {
             Slog.e(TAG, "Unable to contact apexservice", re);
             return false;
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b488337..c0ec367 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -406,7 +406,6 @@
         @Nullable
         private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName,
                 @UserIdInt int userId) {
-            migrateRoleIfNecessary(roleName, userId);
             RoleUserState userState = getOrCreateUserState(userId);
             return userState.getRoleHolders(roleName);
         }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 8021265..d12f7ed 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -977,6 +977,8 @@
                             ensureRollbackDataLoadedLocked();
                             mAvailableRollbacks.add(data);
                         }
+
+                        scheduleExpiration(ROLLBACK_LIFETIME_DURATION_MILLIS);
                     } catch (IOException e) {
                         Log.e(TAG, "Unable to enable rollback", e);
                         removeFile(data.backupDir);
diff --git a/services/core/java/com/android/server/signedconfig/GlobalSettingsConfigApplicator.java b/services/core/java/com/android/server/signedconfig/GlobalSettingsConfigApplicator.java
index 438c303..d77cf90 100644
--- a/services/core/java/com/android/server/signedconfig/GlobalSettingsConfigApplicator.java
+++ b/services/core/java/com/android/server/signedconfig/GlobalSettingsConfigApplicator.java
@@ -23,6 +23,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
+import android.util.StatsLog;
 
 import java.security.GeneralSecurityException;
 import java.util.Arrays;
@@ -66,12 +67,14 @@
 
     private final Context mContext;
     private final String mSourcePackage;
+    private final SignedConfigEvent mEvent;
     private final SignatureVerifier mVerifier;
 
-    GlobalSettingsConfigApplicator(Context context, String sourcePackage) {
+    GlobalSettingsConfigApplicator(Context context, String sourcePackage, SignedConfigEvent event) {
         mContext = context;
         mSourcePackage = sourcePackage;
-        mVerifier = new SignatureVerifier();
+        mEvent = event;
+        mVerifier = new SignatureVerifier(mEvent);
     }
 
     private boolean checkSignature(String data, String signature) {
@@ -79,6 +82,7 @@
             return mVerifier.verifySignature(data, signature);
         } catch (GeneralSecurityException e) {
             Slog.e(TAG, "Failed to verify signature", e);
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__SECURITY_EXCEPTION;
             return false;
         }
     }
@@ -109,14 +113,17 @@
         SignedConfig config;
         try {
             config = SignedConfig.parse(configStr, ALLOWED_KEYS, KEY_VALUE_MAPPERS);
+            mEvent.version = config.version;
         } catch (InvalidConfigException e) {
             Slog.e(TAG, "Failed to parse global settings from package " + mSourcePackage, e);
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__INVALID_CONFIG;
             return;
         }
         int currentVersion = getCurrentConfigVersion();
         if (currentVersion >= config.version) {
             Slog.i(TAG, "Global settings from package " + mSourcePackage
                     + " is older than existing: " + config.version + "<=" + currentVersion);
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__OLD_CONFIG;
             return;
         }
         // We have new config!
@@ -126,10 +133,12 @@
                 config.getMatchingConfig(Build.VERSION.SDK_INT);
         if (matchedConfig == null) {
             Slog.i(TAG, "Settings is not applicable to current SDK version; ignoring");
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__NOT_APPLICABLE;
             return;
         }
 
         Slog.i(TAG, "Updating global settings to version " + config.version);
         updateCurrentConfig(config.version, matchedConfig.values);
+        mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__APPLIED;
     }
 }
diff --git a/services/core/java/com/android/server/signedconfig/SignatureVerifier.java b/services/core/java/com/android/server/signedconfig/SignatureVerifier.java
index 944db84..56db32a 100644
--- a/services/core/java/com/android/server/signedconfig/SignatureVerifier.java
+++ b/services/core/java/com/android/server/signedconfig/SignatureVerifier.java
@@ -18,6 +18,7 @@
 
 import android.os.Build;
 import android.util.Slog;
+import android.util.StatsLog;
 
 import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
@@ -42,11 +43,18 @@
     private static final String DEBUG_KEY =
             "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaAn2XVifsLTHg616nTsOMVmlhBoECGbTEBTKKvdd2hO60"
             + "pj1pnU8SMkhYfaNxZuKgw9LNvOwlFwStboIYeZ3lQ==";
+    private static final String PROD_KEY =
+            "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+lky6wKyGL6lE1VrD0YTMHwb0Xwc+tzC8MvnrzVxodvTp"
+            + "VY/jV7V+Zktcx+pry43XPABFRXtbhTo+qykhyBA1g==";
 
+    private final SignedConfigEvent mEvent;
     private final PublicKey mDebugKey;
+    private final PublicKey mProdKey;
 
-    public SignatureVerifier() {
-        mDebugKey = createKey(DEBUG_KEY);
+    public SignatureVerifier(SignedConfigEvent event) {
+        mEvent = event;
+        mDebugKey = Build.IS_DEBUGGABLE ? createKey(DEBUG_KEY) : null;
+        mProdKey = createKey(PROD_KEY);
     }
 
     private static PublicKey createKey(String base64) {
@@ -67,6 +75,14 @@
         }
     }
 
+    private boolean verifyWithPublicKey(PublicKey key, byte[] data, byte[] signature)
+            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+        Signature verifier = Signature.getInstance("SHA256withECDSA");
+        verifier.initVerify(key);
+        verifier.update(data);
+        return verifier.verify(signature);
+    }
+
     /**
      * Verify a signature for signed config.
      *
@@ -80,6 +96,7 @@
         try {
             signature = Base64.getDecoder().decode(base64Signature);
         } catch (IllegalArgumentException e) {
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__BASE64_FAILURE_SIGNATURE;
             Slog.e(TAG, "Failed to base64 decode signature");
             return false;
         }
@@ -89,11 +106,9 @@
         if (Build.IS_DEBUGGABLE) {
             if (mDebugKey != null) {
                 if (DBG) Slog.w(TAG, "Trying to verify signature using debug key");
-                Signature verifier = Signature.getInstance("SHA256withECDSA");
-                verifier.initVerify(mDebugKey);
-                verifier.update(data);
-                if (verifier.verify(signature)) {
+                if (verifyWithPublicKey(mDebugKey, data, signature)) {
                     Slog.i(TAG, "Verified config using debug key");
+                    mEvent.verifiedWith = StatsLog.SIGNED_CONFIG_REPORTED__VERIFIED_WITH__DEBUG;
                     return true;
                 } else {
                     if (DBG) Slog.i(TAG, "Config verification failed using debug key");
@@ -102,8 +117,20 @@
                 Slog.w(TAG, "Debuggable build, but have no debug key");
             }
         }
-        // TODO verify production key.
-        Slog.w(TAG, "NO PRODUCTION KEY YET, FAILING VERIFICATION");
-        return false;
+        if (mProdKey ==  null) {
+            Slog.e(TAG, "No prod key; construction failed?");
+            mEvent.status =
+                    StatsLog.SIGNED_CONFIG_REPORTED__STATUS__SIGNATURE_CHECK_FAILED_PROD_KEY_ABSENT;
+            return false;
+        }
+        if (verifyWithPublicKey(mProdKey, data, signature)) {
+            Slog.i(TAG, "Verified config using production key");
+            mEvent.verifiedWith = StatsLog.SIGNED_CONFIG_REPORTED__VERIFIED_WITH__PRODUCTION;
+            return true;
+        } else {
+            if (DBG) Slog.i(TAG, "Verification failed using production key");
+            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__SIGNATURE_CHECK_FAILED;
+            return false;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/signedconfig/SignedConfigEvent.java b/services/core/java/com/android/server/signedconfig/SignedConfigEvent.java
new file mode 100644
index 0000000..2f2062c
--- /dev/null
+++ b/services/core/java/com/android/server/signedconfig/SignedConfigEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.signedconfig;
+
+import android.util.StatsLog;
+
+/**
+ * Helper class to allow a SignedConfigReported event to be built up in stages.
+ */
+public class SignedConfigEvent {
+
+    public int type = StatsLog.SIGNED_CONFIG_REPORTED__TYPE__UNKNOWN_TYPE;
+    public int status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__UNKNOWN_STATUS;
+    public int version = 0;
+    public String fromPackage = null;
+    public int verifiedWith = StatsLog.SIGNED_CONFIG_REPORTED__VERIFIED_WITH__NO_KEY;
+
+    /**
+     * Write this event to statslog.
+     */
+    public void send() {
+        StatsLog.write(StatsLog.SIGNED_CONFIG_REPORTED,
+                type, status, version, fromPackage, verifiedWith);
+    }
+
+}
diff --git a/services/core/java/com/android/server/signedconfig/SignedConfigService.java b/services/core/java/com/android/server/signedconfig/SignedConfigService.java
index 6bcee14..dc39542 100644
--- a/services/core/java/com/android/server/signedconfig/SignedConfigService.java
+++ b/services/core/java/com/android/server/signedconfig/SignedConfigService.java
@@ -26,6 +26,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.util.Slog;
+import android.util.StatsLog;
 
 import com.android.server.LocalServices;
 
@@ -82,21 +83,30 @@
         }
         if (metaData.containsKey(KEY_GLOBAL_SETTINGS)
                 && metaData.containsKey(KEY_GLOBAL_SETTINGS_SIGNATURE)) {
-            String config = metaData.getString(KEY_GLOBAL_SETTINGS);
-            String signature = metaData.getString(KEY_GLOBAL_SETTINGS_SIGNATURE);
+            SignedConfigEvent event = new SignedConfigEvent();
             try {
-                // Base64 encoding is standard (not URL safe) encoding: RFC4648
-                config = new String(Base64.getDecoder().decode(config), StandardCharsets.UTF_8);
-            } catch (IllegalArgumentException iae) {
-                Slog.e(TAG, "Failed to base64 decode global settings config from " + packageName);
-                return;
+                event.type = StatsLog.SIGNED_CONFIG_REPORTED__TYPE__GLOBAL_SETTINGS;
+                event.fromPackage = packageName;
+                String config = metaData.getString(KEY_GLOBAL_SETTINGS);
+                String signature = metaData.getString(KEY_GLOBAL_SETTINGS_SIGNATURE);
+                try {
+                    // Base64 encoding is standard (not URL safe) encoding: RFC4648
+                    config = new String(Base64.getDecoder().decode(config), StandardCharsets.UTF_8);
+                } catch (IllegalArgumentException iae) {
+                    Slog.e(TAG, "Failed to base64 decode global settings config from "
+                            + packageName);
+                    event.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__BASE64_FAILURE_CONFIG;
+                    return;
+                }
+                if (DBG) {
+                    Slog.d(TAG, "Got global settings config: " + config);
+                    Slog.d(TAG, "Got global settings signature: " + signature);
+                }
+                new GlobalSettingsConfigApplicator(mContext, packageName, event).applyConfig(
+                        config, signature);
+            } finally {
+                event.send();
             }
-            if (DBG) {
-                Slog.d(TAG, "Got global settings config: " + config);
-                Slog.d(TAG, "Got global settings signature: " + signature);
-            }
-            new GlobalSettingsConfigApplicator(mContext, packageName).applyConfig(
-                    config, signature);
         } else {
             if (DBG) Slog.d(TAG, "Package has no global settings config/signature.");
         }
diff --git a/services/core/java/com/android/server/slice/SlicePermissionManager.java b/services/core/java/com/android/server/slice/SlicePermissionManager.java
index 315d5e3..1d1c28f 100644
--- a/services/core/java/com/android/server/slice/SlicePermissionManager.java
+++ b/services/core/java/com/android/server/slice/SlicePermissionManager.java
@@ -175,18 +175,24 @@
                 handlePersist();
             }
             for (String file : new File(mSliceDir.getAbsolutePath()).list()) {
-                if (file.isEmpty()) continue;
                 try (ParserHolder parser = getParser(file)) {
-                    Persistable p;
-                    while (parser.parser.getEventType() != XmlPullParser.START_TAG) {
+                    Persistable p = null;
+                    while (parser.parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+                        if (parser.parser.getEventType() == XmlPullParser.START_TAG) {
+                            if (SliceClientPermissions.TAG_CLIENT.equals(parser.parser.getName())) {
+                                p = SliceClientPermissions.createFrom(parser.parser, tracker);
+                            } else {
+                                p = SliceProviderPermissions.createFrom(parser.parser, tracker);
+                            }
+                            break;
+                        }
                         parser.parser.next();
                     }
-                    if (SliceClientPermissions.TAG_CLIENT.equals(parser.parser.getName())) {
-                        p = SliceClientPermissions.createFrom(parser.parser, tracker);
+                    if (p != null) {
+                        p.writeTo(out);
                     } else {
-                        p = SliceProviderPermissions.createFrom(parser.parser, tracker);
+                        Slog.w(TAG, "Invalid or empty slice permissions file: " + file);
                     }
-                    p.writeTo(out);
                 }
             }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index a207354..ef3c8d5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.app.Activity.RESULT_CANCELED;
 import static android.app.ActivityManager.START_ABORTED;
 import static android.app.ActivityManager.START_CANCELED;
@@ -50,6 +51,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
@@ -745,8 +747,9 @@
         // not sure if we need to create START_ABORTED_BACKGROUND so for now piggybacking
         // on START_ABORTED
         if (!abort) {
-            abort |= shouldAbortBackgroundActivityStart(callingUid, callingPackage, realCallingUid,
-                    callerApp, originatingPendingIntent, allowBackgroundActivityStart);
+            abort |= shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage,
+                    realCallingUid, callerApp, originatingPendingIntent,
+                    allowBackgroundActivityStart);
         }
 
         // Merge the two options bundles, while realCallerOptions takes precedence.
@@ -893,8 +896,8 @@
                 true /* doResume */, checkedOptions, inTask, outActivity);
     }
 
-    private boolean shouldAbortBackgroundActivityStart(int callingUid, final String callingPackage,
-            int realCallingUid, WindowProcessController callerApp,
+    private boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
+            final String callingPackage, int realCallingUid, WindowProcessController callerApp,
             PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
         if (mService.isBackgroundActivityStartsEnabled()) {
             return false;
@@ -928,6 +931,11 @@
         if (callerApp != null && callerApp.areBackgroundActivityStartsAllowed()) {
             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) {
+            return false;
+        }
         // don't abort if the caller has the same uid as the recents component
         if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
             return false;
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
index 0d3b6b2..b8db3f3 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -46,6 +46,7 @@
 import android.util.SparseArray;
 
 import com.android.server.backup.testing.TransportData;
+import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 import com.android.server.testing.shadows.ShadowBinder;
 
 import org.junit.After;
@@ -65,7 +66,7 @@
 
 /** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowBinder.class})
+@Config(shadows = {ShadowApplicationPackageManager.class, ShadowBinder.class})
 @Presubmit
 public class BackupManagerServiceTest {
     private static final String TEST_PACKAGE = "package";
diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
index 4968176..3b7fa3d 100644
--- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -42,6 +42,8 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.os.Binder;
 import android.os.HandlerThread;
 import android.os.PowerManager;
@@ -54,6 +56,7 @@
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
+import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 import com.android.server.testing.shadows.ShadowBinder;
 import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
 import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
@@ -80,7 +83,7 @@
  * UserBackupManagerService} that performs operations for its target user.
  */
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowAppBackupUtils.class})
+@Config(shadows = {ShadowAppBackupUtils.class, ShadowApplicationPackageManager.class})
 @Presubmit
 public class UserBackupManagerServiceTest {
     private static final String TAG = "BMSTest";
@@ -137,6 +140,7 @@
     public void tearDown() throws Exception {
         mBackupThread.quit();
         ShadowAppBackupUtils.reset();
+        ShadowApplicationPackageManager.reset();
     }
 
     /**
@@ -195,6 +199,7 @@
     public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
+        registerPackages(PACKAGE_1);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1);
@@ -210,6 +215,7 @@
     public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
+        registerPackages(PACKAGE_1);
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
@@ -228,6 +234,7 @@
     public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
+        registerPackages(PACKAGE_1);
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
@@ -245,6 +252,7 @@
     public void testFilterAppsEligibleForBackup() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
+        registerPackages(PACKAGE_1, PACKAGE_2);
         ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
@@ -264,6 +272,7 @@
     @Test
     public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        registerPackages(PACKAGE_1, PACKAGE_2);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         String[] filtered =
@@ -281,6 +290,7 @@
     public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception {
         mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
         setUpCurrentTransport(mTransportManager, mTransport);
+        registerPackages(PACKAGE_1, PACKAGE_2);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
 
         expectThrows(
@@ -749,7 +759,7 @@
     private void setUpForRequestBackup(String... packages) throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
         for (String packageName : packages) {
-            mShadowPackageManager.addPackage(packageName);
+            registerPackages(packageName);
             ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(packageName);
         }
         setUpCurrentTransport(mTransportManager, mTransport);
@@ -864,7 +874,7 @@
     @Test
     public void testRequestBackup_whenAppNotEligibleForBackup() throws Exception {
         mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
-        mShadowPackageManager.addPackage(PACKAGE_1);
+        registerPackages(PACKAGE_1);
         setUpCurrentTransport(mTransportManager, mTransport);
         UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks();
         backupManagerService.setEnabled(true);
@@ -1127,6 +1137,22 @@
         backupManagerService.setPowerManager(powerManagerMock);
     }
 
+    private PackageInfo getPackageInfo(String packageName) {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = packageName;
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.packageName = packageName;
+        return packageInfo;
+    }
+
+    private void registerPackages(String... packages) {
+        for (String packageName : packages) {
+            PackageInfo packageInfo = getPackageInfo(packageName);
+            mShadowPackageManager.installPackage(packageInfo);
+            ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo);
+        }
+    }
+
     /**
      * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we
      * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method.
diff --git a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
index b08ae6d..bfb2b14 100644
--- a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java
@@ -29,6 +29,7 @@
 import com.android.server.backup.UserBackupManagerService;
 import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TestUtils;
+import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -37,6 +38,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 import java.io.File;
 
@@ -45,6 +47,7 @@
  * UserBackupManagerService}.
  */
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowApplicationPackageManager.class})
 @Presubmit
 public class SetupObserverTest {
     private static final String TAG = "SetupObserverTest";
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 b923bb0..4811523 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
@@ -71,7 +71,6 @@
 
 import android.annotation.Nullable;
 import android.app.Application;
-import android.app.ApplicationPackageManager;
 import android.app.IBackupAgent;
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupDataInput;
@@ -116,6 +115,7 @@
 import com.android.server.backup.testing.TransportTestUtils;
 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.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -135,8 +135,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowQueuedWork;
@@ -160,7 +158,7 @@
 @Config(
         shadows = {
             FrameworkShadowLooper.class,
-            KeyValueBackupTaskTest.ShadowApplicationPackageManager.class,
+            ShadowApplicationPackageManager.class,
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEventLog.class,
@@ -2437,11 +2435,12 @@
 
     private AgentMock setUpAgent(PackageData packageData) {
         try {
+            String packageName = packageData.packageName;
             mPackageManager.setApplicationEnabledSetting(
-                    packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+                    packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             PackageInfo packageInfo = getPackageInfo(packageData);
             mShadowPackageManager.installPackage(packageInfo);
-            ShadowApplicationPackageManager.setPackageInfo(packageInfo);
+            ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo);
             mContext.sendBroadcast(getPackageAddedIntent(packageData));
             // Run the backup looper because on the receiver we post MSG_SCHEDULE_BACKUP_PACKAGE
             mShadowBackupLooper.runToEndOfTasks();
@@ -2537,7 +2536,7 @@
 
     private PackageManagerBackupAgent createPmAgent() {
         PackageManagerBackupAgent pmAgent =
-                new PackageManagerBackupAgent(mApplication.getPackageManager());
+                new PackageManagerBackupAgent(mApplication.getPackageManager(), USER_ID);
         pmAgent.attach(mApplication);
         pmAgent.onCreate();
         return pmAgent;
@@ -2842,7 +2841,7 @@
 
         ThrowingPackageManagerBackupAgent(
                 PackageManager packageManager, RuntimeException exception) {
-            super(packageManager);
+            super(packageManager, USER_ID);
             mException = exception;
         }
 
@@ -2854,29 +2853,4 @@
             throw mException;
         }
     }
-
-    /**
-     * Extends {@link org.robolectric.shadows.ShadowApplicationPackageManager} to return the correct
-     * package in user-specific invocations.
-     */
-    @Implements(value = ApplicationPackageManager.class)
-    public static class ShadowApplicationPackageManager
-            extends org.robolectric.shadows.ShadowApplicationPackageManager {
-        private static PackageInfo sPackageInfo;
-
-        static void setPackageInfo(PackageInfo packageInfo) {
-            sPackageInfo = packageInfo;
-        }
-
-        @Override
-        protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) {
-            return sPackageInfo;
-        }
-
-        /** Clear {@link #sPackageInfo}. */
-        @Resetter
-        public static void reset() {
-            sPackageInfo = null;
-        }
-    }
 }
diff --git a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 4009876..f17a9fe 100644
--- a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -57,6 +57,7 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
+import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask;
 
@@ -77,7 +78,13 @@
 import java.util.ArrayDeque;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
+@Config(
+        shadows = {
+            ShadowApplicationPackageManager.class,
+            ShadowBinder.class,
+            ShadowEventLog.class,
+            ShadowPerformUnifiedRestoreTask.class
+        })
 @Presubmit
 public class ActiveRestoreSessionTest {
     private static final String PACKAGE_1 = "com.example.package1";
@@ -140,6 +147,7 @@
 
     @After
     public void tearDown() throws Exception {
+        ShadowApplicationPackageManager.reset();
         ShadowPerformUnifiedRestoreTask.reset();
     }
 
@@ -561,7 +569,8 @@
         packageInfo.packageName = packageName;
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.uid = uid;
-        mShadowPackageManager.addPackage(packageInfo);
+        mShadowPackageManager.installPackage(packageInfo);
+        ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo);
     }
 
     private IRestoreSession createActiveRestoreSession(
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
index 5fffb14..aefc871 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
@@ -54,7 +54,10 @@
 
     @Implementation
     protected static boolean appIsRunningAndEligibleForBackupWithTransport(
-            @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
+            @Nullable TransportClient transportClient,
+            String packageName,
+            PackageManager pm,
+            int userId) {
         return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName);
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
new file mode 100644
index 0000000..dc32209
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.testing.shadows;
+
+import static android.content.pm.PackageManager.NameNotFoundException;
+
+import android.app.ApplicationPackageManager;
+import android.content.pm.PackageInfo;
+import android.util.ArrayMap;
+
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Extends {@link org.robolectric.shadows.ShadowApplicationPackageManager} to return the correct
+ * package in user-specific invocations.
+ */
+@Implements(value = ApplicationPackageManager.class)
+public class ShadowApplicationPackageManager
+        extends org.robolectric.shadows.ShadowApplicationPackageManager {
+    private static final Map<String, PackageInfo> sPackageInfos = new ArrayMap<>();
+    private static final List<PackageInfo> sInstalledPackages = new ArrayList<>();
+
+    /**
+     * Registers the package {@code packageName} to be returned when invoking {@link
+     * ApplicationPackageManager#getPackageInfoAsUser(String, int, int)} and {@link
+     * ApplicationPackageManager#getInstalledPackagesAsUser(int, int)}.
+     */
+    public static void addInstalledPackage(String packageName, PackageInfo packageInfo) {
+        sPackageInfos.put(packageName, packageInfo);
+        sInstalledPackages.add(packageInfo);
+    }
+
+    @Override
+    protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
+            throws NameNotFoundException {
+        if (!sPackageInfos.containsKey(packageName)) {
+            throw new NameNotFoundException(packageName);
+        }
+        return sPackageInfos.get(packageName);
+    }
+
+    @Override
+    protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
+        return sInstalledPackages;
+    }
+
+    /** Clear package state. */
+    @Resetter
+    public static void reset() {
+        sPackageInfos.clear();
+        sInstalledPackages.clear();
+        org.robolectric.shadows.ShadowApplicationPackageManager.reset();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
index 8109b1c..1dfce51 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.server.appop.AppOpsService;
+import com.android.server.wm.ActivityTaskManagerService;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -62,13 +63,15 @@
                 return false;
             }
         });
+        mService.mActivityTaskManager = new ActivityTaskManagerService(mContext);
+        mService.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
     }
 
     @Test
     @UiThreadTest
     public void testCreateWorks() {
         AppErrorDialog.Data data = new AppErrorDialog.Data();
-        data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345);
+        data.proc = new ProcessRecord(mService, mContext.getApplicationInfo(), "name", 12345);
         data.result = new AppErrorResult();
 
         AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data);
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 517b5ad..6d28ed1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -35,6 +35,7 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.SuspendDialogInfo;
@@ -226,8 +227,8 @@
         settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
         // now read and verify
         settingsUnderTest.readPackageRestrictionsLPr(0);
-        final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1).
-                readUserState(0);
+        final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
+                .readUserState(0);
         assertThat(readPus1.suspended, is(true));
         assertThat(readPus1.suspendingPackage, equalTo("suspendingPackage1"));
         assertThat(readPus1.dialogInfo, equalTo(dialogInfo1));
@@ -235,16 +236,16 @@
         assertThat(BaseBundle.kindofEquals(readPus1.suspendedLauncherExtras, launcherExtras1),
                 is(true));
 
-        final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2).
-                readUserState(0);
+        final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
+                .readUserState(0);
         assertThat(readPus2.suspended, is(true));
         assertThat(readPus2.suspendingPackage, equalTo("suspendingPackage2"));
         assertThat(readPus2.dialogInfo, is(nullValue()));
         assertThat(readPus2.suspendedAppExtras, is(nullValue()));
         assertThat(readPus2.suspendedLauncherExtras, is(nullValue()));
 
-        final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3).
-                readUserState(0);
+        final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
+                .readUserState(0);
         assertThat(readPus3.suspended, is(false));
         assertThat(readPus3.suspendingPackage, is(nullValue()));
         assertThat(readPus3.dialogInfo, is(nullValue()));
@@ -254,11 +255,59 @@
 
     @Test
     public void testPackageRestrictionsSuspendedDefault() {
-        final PackageSetting defaultSetting =  createPackageSetting(PACKAGE_NAME_1);
+        final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
         assertThat(defaultSetting.getSuspended(0), is(false));
     }
 
     @Test
+    public void testReadWritePackageRestrictions_distractionFlags() {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, new Object());
+        final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+        final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
+        final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
+
+        final int distractionFlags1 = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
+        ps1.setDistractionFlags(distractionFlags1, 0);
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
+
+        final int distractionFlags2 = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS
+                | PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
+        ps2.setDistractionFlags(distractionFlags2, 0);
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
+
+        final int distractionFlags3 = PackageManager.RESTRICTION_NONE;
+        ps3.setDistractionFlags(distractionFlags3, 0);
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
+
+        settingsUnderTest.writePackageRestrictionsLPr(0);
+
+        settingsUnderTest.mPackages.clear();
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
+        // now read and verify
+        settingsUnderTest.readPackageRestrictionsLPr(0);
+        final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
+                .readUserState(0);
+        assertThat(readPus1.distractionFlags, is(distractionFlags1));
+
+        final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
+                .readUserState(0);
+        assertThat(readPus2.distractionFlags, is(distractionFlags2));
+
+        final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
+                .readUserState(0);
+        assertThat(readPus3.distractionFlags, is(distractionFlags3));
+    }
+
+    @Test
+    public void testPackageRestrictionsDistractionFlagsDefault() {
+        final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
+        assertThat(defaultSetting.getDistractionFlags(0), is(PackageManager.RESTRICTION_NONE));
+    }
+
+    @Test
     public void testEnableDisable() {
         // Write the package files and make sure they're parsed properly the first time
         writeOldFiles();
@@ -692,6 +741,7 @@
         assertThat(userState.notLaunched, is(notLaunched));
         assertThat(userState.stopped, is(stopped));
         assertThat(userState.suspended, is(false));
+        assertThat(userState.distractionFlags, is(0));
         if (oldUserState != null) {
             assertThat(userState.equals(oldUserState), is(not(userStateChanged)));
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index f0ed612..8eaf35f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -22,6 +22,7 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
+import android.content.pm.PackageManager;
 import android.content.pm.PackageUserState;
 import android.content.pm.SuspendDialogInfo;
 import android.os.PersistableBundle;
@@ -227,4 +228,19 @@
         assertThat(testUserState1.equals(testUserState2), is(true));
     }
 
+    @Test
+    public void testPackageUserState06() {
+        final PackageUserState userState1 = new PackageUserState();
+        assertThat(userState1.distractionFlags, is(PackageManager.RESTRICTION_NONE));
+        userState1.distractionFlags = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
+
+        final PackageUserState copyOfUserState1 = new PackageUserState(userState1);
+        assertThat(userState1.distractionFlags, is(copyOfUserState1.distractionFlags));
+        assertThat(userState1.equals(copyOfUserState1), is(true));
+
+        final PackageUserState userState2 = new PackageUserState(userState1);
+        userState2.distractionFlags = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS;
+        assertThat(userState1.equals(userState2), is(false));
+    }
+
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
index b315e51..efefee1 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
@@ -16,6 +16,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -26,6 +27,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.util.Log;
 import android.util.Xml.Encoding;
 
 import com.android.server.UiServiceTestCase;
@@ -46,10 +48,12 @@
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 public class SlicePermissionManagerTest extends UiServiceTestCase {
+    private static final String TAG = "SlicePerManTest";
 
     @Test
     public void testGrant() {
-        File sliceDir = new File(mContext.getDataDir(), "system/slices");
+        File sliceDir = new File(mContext.getCacheDir(), "testGrantSlices");
+        Log.v(TAG, "testGrant: slice permissions stored in " + sliceDir.getAbsolutePath());
         SlicePermissionManager permissions = new SlicePermissionManager(mContext,
                 TestableLooper.get(this).getLooper(), sliceDir);
         Uri uri = new Builder().scheme(ContentResolver.SCHEME_CONTENT)
@@ -59,11 +63,15 @@
         permissions.grantSliceAccess("my.pkg", 0, "provider.pkg", 0, uri);
 
         assertTrue(permissions.hasPermission("my.pkg", 0, uri));
+
+        // Cleanup.
+        assertTrue(FileUtils.deleteContentsAndDir(sliceDir));
     }
 
     @Test
     public void testBackup() throws XmlPullParserException, IOException {
-        File sliceDir = new File(mContext.getDataDir(), "system/slices");
+        File sliceDir = new File(mContext.getCacheDir(), "testBackupSlices");
+        Log.v(TAG, "testBackup: slice permissions stored in " + sliceDir.getAbsolutePath());
         Uri uri = new Builder().scheme(ContentResolver.SCHEME_CONTENT)
                 .authority("authority")
                 .path("something").build();
@@ -90,7 +98,10 @@
                 TestableLooper.get(this).getLooper());
         permissions.readRestore(parser);
 
-        assertTrue(permissions.hasFullAccess("com.android.mypkg", 10));
+        if (!permissions.hasFullAccess("com.android.mypkg", 10)) {
+            fail("com.android.mypkg@10 did not have full access. backup file: "
+                    + output.toString());
+        }
         assertTrue(permissions.hasPermission("com.android.otherpkg", 0,
                 ContentProvider.maybeAddUserId(uri, 1)));
         permissions.removePkg("com.android.lastpkg", 1);
@@ -102,8 +113,9 @@
     }
 
     @Test
-    public void testInvalid() throws Exception {
-        File sliceDir = new File(mContext.getCacheDir(), "slices-test");
+    public void testInvalid() {
+        File sliceDir = new File(mContext.getCacheDir(), "testInvalidSlices");
+        Log.v(TAG, "testInvalid: slice permissions stored in " + sliceDir.getAbsolutePath());
         if (!sliceDir.exists()) {
             sliceDir.mkdir();
         }
@@ -118,7 +130,8 @@
 
             @Override
             public void writeTo(XmlSerializer out) throws IOException {
-                throw new RuntimeException("this doesn't work");
+                throw new RuntimeException("this RuntimeException inside junk.writeTo() "
+                        + "should be caught and suppressed by surrounding code");
             }
         };
 
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 904d55e..00c7548 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -418,12 +418,10 @@
                         parser.getRawDescriptors());
 
                 // Stats collection
-                if (parser.hasAudioInterface()) {
-                    StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, newDevice.getVendorId(),
-                            newDevice.getProductId(), parser.hasAudioInterface(),
-                            parser.hasHIDInterface(), parser.hasStorageInterface(),
-                            StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_CONNECTED, 0);
-                }
+                StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, newDevice.getVendorId(),
+                        newDevice.getProductId(), parser.hasAudioInterface(),
+                        parser.hasHIDInterface(), parser.hasStorageInterface(),
+                        StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_CONNECTED, 0);
             }
         }
 
@@ -455,14 +453,12 @@
                 if (current != null) {
                     UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress,
                             current.mDescriptors);
-                    if (parser.hasAudioInterface()) {
                         // Stats collection
-                        StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, device.getVendorId(),
-                                device.getProductId(), parser.hasAudioInterface(),
-                                parser.hasHIDInterface(),  parser.hasStorageInterface(),
-                                StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_DISCONNECTED,
-                                System.currentTimeMillis() - current.mTimestamp);
-                    }
+                    StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, device.getVendorId(),
+                            device.getProductId(), parser.hasAudioInterface(),
+                            parser.hasHIDInterface(),  parser.hasStorageInterface(),
+                            StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_DISCONNECTED,
+                            System.currentTimeMillis() - current.mTimestamp);
                 }
             } else {
                 Slog.d(TAG, "Removed device at " + deviceAddress + " was already gone");
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index 2fc3a0d..7dc83c3 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -46,7 +46,7 @@
     },
 }
 
-cc_library_host_static {
+cc_library_static {
     name: "libviewcompiler",
     defaults: ["viewcompiler_defaults"],
     srcs: [
@@ -58,9 +58,10 @@
         "util.cc",
         "layout_validation.cc",
     ],
+    host_supported: true,
 }
 
-cc_binary_host {
+cc_binary {
     name: "viewcompiler",
     defaults: ["viewcompiler_defaults"],
     srcs: [
@@ -70,6 +71,7 @@
         "libgflags",
         "libviewcompiler",
     ],
+    host_supported: true
 }
 
 cc_test_host {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 8425603..05d5a13 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -505,6 +505,14 @@
             "android.telecom.extra.ORIGINAL_CONNECTION_ID";
 
     /**
+     * Boolean connection extra key set on the extras passed to
+     * {@link Connection#sendConnectionEvent} which indicates that audio is present
+     * on the RTT call when the extra value is true.
+     */
+    public static final String EXTRA_IS_RTT_AUDIO_PRESENT =
+            "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
+
+    /**
      * Connection event used to inform Telecom that it should play the on hold tone.  This is used
      * to play a tone when the peer puts the current call on hold.  Sent to Telecom via
      * {@link #sendConnectionEvent(String, Bundle)}.
@@ -619,6 +627,13 @@
      */
     public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
 
+    /**
+     * Connection event used to inform an {@link InCallService} that the RTT audio indication
+     * has changed.
+     */
+    public static final String EVENT_RTT_AUDIO_INDICATION_CHANGED =
+            "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED";
+
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index a16d7eb..c816701 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -296,7 +296,7 @@
 
     /**
      *  Listen for changes to preferred data subId.
-     *  See {@link SubscriptionManager#setPreferredData(int)}
+     *  See {@link SubscriptionManager#setPreferredDataSubId(int)}
      *  for more details.
      *
      *  @see #onPreferredDataSubIdChanged
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 34f7abd..9fa4c3c 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2453,10 +2453,39 @@
      *
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void setPreferredData(int subId) {
-        if (VDBG) logd("[setPreferredData]+ subId:" + subId);
-        setSubscriptionPropertyHelper(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
-                "setPreferredData", (iSub)-> iSub.setPreferredData(subId));
+    public void setPreferredDataSubscriptionId(int subId) {
+        if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
+        setSubscriptionPropertyHelper(DEFAULT_SUBSCRIPTION_ID, "setPreferredDataSubscriptionId",
+                (iSub)-> iSub.setPreferredDataSubscriptionId(subId));
+    }
+
+    /**
+     * Get which subscription is preferred for cellular data.
+     * It's also usually the subscription we set up internet connection on.
+     *
+     * PreferredData overwrites user setting of default data subscription. And it's used
+     * by AlternativeNetworkService or carrier apps to switch primary and CBRS
+     * subscription dynamically in multi-SIM devices.
+     *
+     * @return preferred subscription id for cellular data. {@link DEFAULT_SUBSCRIPTION_ID} if
+     * there's no prefered subscription.
+     *
+     * @hide
+     *
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getPreferredDataSubscriptionId() {
+        int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                preferredSubId = iSub.getPreferredDataSubscriptionId();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return preferredSubId;
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 7f7d5e7..babeb7b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9910,10 +9910,11 @@
         try {
             IOns iOpportunisticNetworkService = getIOns();
             if (iOpportunisticNetworkService != null) {
-                return iOpportunisticNetworkService.setPreferredData(subId, pkgForDebug);
+                return iOpportunisticNetworkService
+                        .setPreferredDataSubscriptionId(subId, pkgForDebug);
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "setPreferredData RemoteException", ex);
+            Rlog.e(TAG, "setPreferredDataSubscriptionId RemoteException", ex);
         }
         return false;
     }
@@ -9934,10 +9935,10 @@
         try {
             IOns iOpportunisticNetworkService = getIOns();
             if (iOpportunisticNetworkService != null) {
-                subId = iOpportunisticNetworkService.getPreferredData(pkgForDebug);
+                subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(pkgForDebug);
             }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getPreferredData RemoteException", ex);
+            Rlog.e(TAG, "getPreferredDataSubscriptionId RemoteException", ex);
         }
         return subId;
     }
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index cc9befe..42a788d 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -30,6 +30,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.euicc.IEuiccController;
 
@@ -40,7 +41,11 @@
  * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs.
  *
  * <p>You do not instantiate this class directly; instead, you retrieve an instance through
- * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}.
+ * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. This instance will be
+ * created using the default eUICC.
+ *
+ * <p>On a device with multiple eUICCs, you may want to create multiple EuiccManagers. To do this
+ * you can call {@link #createForCardId}.
  *
  * <p>See {@link #isEnabled} before attempting to use these APIs.
  */
@@ -318,10 +323,29 @@
     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
 
     private final Context mContext;
+    private final int mCardId;
 
     /** @hide */
     public EuiccManager(Context context) {
         mContext = context;
+        TelephonyManager tm = (TelephonyManager)
+                context.getSystemService(Context.TELEPHONY_SERVICE);
+        mCardId = tm.getCardIdForDefaultEuicc();
+    }
+
+    /** @hide */
+    private EuiccManager(Context context, int cardId) {
+        mContext = context;
+        mCardId = cardId;
+    }
+
+    /**
+     * Create a new EuiccManager object pinned to the given card ID.
+     *
+     * @return an EuiccManager that uses the given card ID for all calls.
+     */
+    public EuiccManager createForCardId(int cardId) {
+        return new EuiccManager(mContext, cardId);
     }
 
     /**
@@ -344,7 +368,8 @@
      * Returns the EID identifying the eUICC hardware.
      *
      * <p>Requires that the calling app has carrier privileges on the active subscription on the
-     * eUICC.
+     * current eUICC. A calling app with carrier privileges for one eUICC may not necessarily have
+     * access to the EID of another eUICC.
      *
      * @return the EID. May be null if {@link #isEnabled()} is false or the eUICC is not ready.
      */
@@ -354,7 +379,7 @@
             return null;
         }
         try {
-            return getIEuiccController().getEid();
+            return getIEuiccController().getEid(mCardId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -377,7 +402,7 @@
             return EUICC_OTA_STATUS_UNAVAILABLE;
         }
         try {
-            return getIEuiccController().getOtaStatus();
+            return getIEuiccController().getOtaStatus(mCardId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -387,10 +412,10 @@
      * Attempt to download the given {@link DownloadableSubscription}.
      *
      * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
-     * or the calling app must be authorized to manage both the currently-active subscription and
-     * the subscription to be downloaded according to the subscription metadata. Without the former,
-     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
-     * intent to prompt the user to accept the download.
+     * or the calling app must be authorized to manage both the currently-active subscription on the
+     * current eUICC and the subscription to be downloaded according to the subscription metadata.
+     * Without the former, an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be
+     * returned in the callback intent to prompt the user to accept the download.
      *
      * @param subscription the subscription to download.
      * @param switchAfterDownload if true, the profile will be activated upon successful download.
@@ -404,7 +429,7 @@
             return;
         }
         try {
-            getIEuiccController().downloadSubscription(subscription, switchAfterDownload,
+            getIEuiccController().downloadSubscription(mCardId, subscription, switchAfterDownload,
                     mContext.getOpPackageName(), null /* resolvedBundle */, callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -471,7 +496,7 @@
             return;
         }
         try {
-            getIEuiccController().continueOperation(resolutionIntent, resolutionExtras);
+            getIEuiccController().continueOperation(mCardId, resolutionIntent, resolutionExtras);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -503,8 +528,8 @@
             return;
         }
         try {
-            getIEuiccController().getDownloadableSubscriptionMetadata(
-                    subscription, mContext.getOpPackageName(), callbackIntent);
+            getIEuiccController().getDownloadableSubscriptionMetadata(mCardId, subscription,
+                    mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -533,7 +558,7 @@
             return;
         }
         try {
-            getIEuiccController().getDefaultDownloadableSubscriptionList(
+            getIEuiccController().getDefaultDownloadableSubscriptionList(mCardId,
                     mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -552,7 +577,7 @@
             return null;
         }
         try {
-            return getIEuiccController().getEuiccInfo();
+            return getIEuiccController().getEuiccInfo(mCardId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -578,7 +603,7 @@
             return;
         }
         try {
-            getIEuiccController().deleteSubscription(
+            getIEuiccController().deleteSubscription(mCardId,
                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -606,7 +631,7 @@
             return;
         }
         try {
-            getIEuiccController().switchToSubscription(
+            getIEuiccController().switchToSubscription(mCardId,
                     subscriptionId, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -632,7 +657,7 @@
             return;
         }
         try {
-            getIEuiccController().updateSubscriptionNickname(
+            getIEuiccController().updateSubscriptionNickname(mCardId,
                     subscriptionId, nickname, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -656,7 +681,7 @@
             return;
         }
         try {
-            getIEuiccController().eraseSubscriptions(callbackIntent);
+            getIEuiccController().eraseSubscriptions(mCardId, callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -686,7 +711,7 @@
             return;
         }
         try {
-            getIEuiccController().retainSubscriptionsForFactoryReset(callbackIntent);
+            getIEuiccController().retainSubscriptionsForFactoryReset(mCardId, callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index df903cc2..397d5d9 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -443,6 +443,13 @@
         public void callSessionRttMessageReceived(String rttMessage) {
             // no-op
         }
+
+        /**
+         * While in call, there has been a change in RTT audio indicator.
+         */
+        public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
+            // no-op
+        }
     }
 
     private final IImsCallSession miSession;
@@ -1397,6 +1404,16 @@
                 mListener.callSessionRttMessageReceived(rttMessage);
             }
         }
+
+        /**
+         * While in call, there has been a change in RTT audio indicator.
+         */
+        @Override
+        public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
+            if (mListener != null) {
+                mListener.callSessionRttAudioIndicatorChanged(profile);
+            }
+        }
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index a7f124a..a4696a3 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -599,5 +599,18 @@
             throw new RuntimeException(e);
         }
     }
+
+    /**
+     * While in call, there has been a change in RTT audio indicator.
+     *
+     * @param profile updated ImsStreamMediaProfile
+     */
+    public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
+        try {
+            mListener.callSessionRttAudioIndicatorChanged(profile);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
 
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index 52d72b5..837ef54 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -97,6 +97,9 @@
     // Rtt related information
     /** @hide */
     public int mRttMode;
+    // RTT Audio Speech Indicator
+    /** @hide */
+    public boolean mHasRttAudioSpeech = false;
 
     /** @hide */
     public ImsStreamMediaProfile(Parcel in) {
@@ -197,7 +200,8 @@
                 ", audioDirection=" + mAudioDirection +
                 ", videoQuality=" + mVideoQuality +
                 ", videoDirection=" + mVideoDirection +
-                ", rttMode=" + mRttMode + " }";
+                ", rttMode=" + mRttMode +
+                ", hasRttAudioSpeech=" + mHasRttAudioSpeech + " }";
     }
 
     @Override
@@ -212,6 +216,7 @@
         out.writeInt(mVideoQuality);
         out.writeInt(mVideoDirection);
         out.writeInt(mRttMode);
+        out.writeBoolean(mHasRttAudioSpeech);
     }
 
     private void readFromParcel(Parcel in) {
@@ -220,6 +225,7 @@
         mVideoQuality = in.readInt();
         mVideoDirection = in.readInt();
         mRttMode = in.readInt();
+        mHasRttAudioSpeech = in.readBoolean();
     }
 
     public static final Creator<ImsStreamMediaProfile> CREATOR =
@@ -250,6 +256,10 @@
         mRttMode = rttMode;
     }
 
+    public void setRttAudioSpeech(boolean audioOn) {
+        mHasRttAudioSpeech = audioOn;
+    }
+
     public int getAudioQuality() {
         return mAudioQuality;
     }
@@ -269,4 +279,8 @@
     public int getRttMode() {
         return mRttMode;
     }
+
+    public boolean getRttAudioSpeech() {
+        return mHasRttAudioSpeech;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
index f25b4b1..d0b31e1 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
@@ -138,4 +138,10 @@
      * @param rttMessage Received RTT message
      */
     void callSessionRttMessageReceived(in String rttMessage);
+
+    /*
+     * While in call, there has been a change in RTT audio indicator.
+     * @param profile updated ImsStreamMediaProfile
+     */
+    void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile);
 }
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index 23de2fd..bc58e46 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -591,5 +591,11 @@
         public void callSessionRttMessageReceived(String rttMessage) throws RemoteException {
             mNewListener.callSessionRttMessageReceived(rttMessage);
         }
+
+        @Override
+        public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile)
+                throws RemoteException {
+            mNewListener.callSessionRttAudioIndicatorChanged(profile);
+        }
     }
 }
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index a8e8b7dd..bbb27af 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -152,4 +152,10 @@
      * @param rttMessage Received RTT message
      */
     void callSessionRttMessageReceived(in String rttMessage);
+
+    /*
+     * While in call, there has been a change in RTT audio indicator.
+     * @param profile updated ImsStreamMediaProfile
+     */
+    void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile);
 }
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index d6779f1..0e3d12b 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -66,7 +66,7 @@
      * @return true if request is accepted, else false.
      *
      */
-    boolean setPreferredData(int subId, String callingPackage);
+    boolean setPreferredDataSubscriptionId(int subId, String callingPackage);
 
     /**
      * Get preferred opportunistic data subscription Id
@@ -78,7 +78,7 @@
      * subscription id
      *
      */
-    int getPreferredData(String callingPackage);
+    int getPreferredDataSubscriptionId(String callingPackage);
 
     /**
      * Update availability of a list of networks in the current location.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index d169b7d..577ddbd 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -200,7 +200,15 @@
      * @hide
      *
      */
-    int setPreferredData(int subId);
+    int setPreferredDataSubscriptionId(int subId);
+
+    /**
+     * Get which subscription is preferred for cellular data.
+     *
+     * @hide
+     *
+     */
+    int getPreferredDataSubscriptionId();
 
     /**
      * Get User downloaded Profiles.
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index dd40d56..14a36c8 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -24,22 +24,25 @@
 
 /** @hide */
 interface IEuiccController {
-    oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras);
-    oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription,
+    oneway void continueOperation(int cardId, in Intent resolutionIntent,
+            in Bundle resolutionExtras);
+    oneway void getDownloadableSubscriptionMetadata(int cardId,
+            in DownloadableSubscription subscription,
         String callingPackage, in PendingIntent callbackIntent);
-    oneway void getDefaultDownloadableSubscriptionList(
+    oneway void getDefaultDownloadableSubscriptionList(int cardId,
         String callingPackage, in PendingIntent callbackIntent);
-    String getEid();
-    int getOtaStatus();
-    oneway void downloadSubscription(in DownloadableSubscription subscription,
-        boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle, in PendingIntent callbackIntent);
-    EuiccInfo getEuiccInfo();
-    oneway void deleteSubscription(int subscriptionId, String callingPackage,
+    String getEid(int cardId);
+    int getOtaStatus(int cardId);
+    oneway void downloadSubscription(int cardId, in DownloadableSubscription subscription,
+        boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle,
         in PendingIntent callbackIntent);
-    oneway void switchToSubscription(int subscriptionId, String callingPackage,
+    EuiccInfo getEuiccInfo(int cardId);
+    oneway void deleteSubscription(int cardId, int subscriptionId, String callingPackage,
         in PendingIntent callbackIntent);
-    oneway void updateSubscriptionNickname(int subscriptionId, String nickname,
+    oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage,
+        in PendingIntent callbackIntent);
+    oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
         String callingPackage, in PendingIntent callbackIntent);
-    oneway void eraseSubscriptions(in PendingIntent callbackIntent);
-    oneway void retainSubscriptionsForFactoryReset(in PendingIntent callbackIntent);
-}
\ No newline at end of file
+    oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
+    oneway void retainSubscriptionsForFactoryReset(int cardId, in PendingIntent callbackIntent);
+}
diff --git a/tests/PackageWatchdog/Android.mk b/tests/PackageWatchdog/Android.mk
index b53f27d..1c1c2a4 100644
--- a/tests/PackageWatchdog/Android.mk
+++ b/tests/PackageWatchdog/Android.mk
@@ -23,7 +23,7 @@
     junit \
     frameworks-base-testutils \
     android-support-test \
-    services
+    services.core
 
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner
diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
index f82b380..932fee0 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -18,6 +18,7 @@
 
 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 static org.junit.Assert.fail;
 
@@ -33,6 +34,9 @@
 import android.system.OsConstants;
 import android.util.ArraySet;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,9 +45,6 @@
 import java.util.List;
 import java.util.Set;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class LinkPropertiesTest {
@@ -504,6 +505,40 @@
     }
 
     @Test
+    public void testNat64Prefix() throws Exception {
+        LinkProperties lp = new LinkProperties();
+        lp.addLinkAddress(LINKADDRV4);
+        lp.addLinkAddress(LINKADDRV6);
+
+        assertNull(lp.getNat64Prefix());
+
+        IpPrefix p = new IpPrefix("64:ff9b::/96");
+        lp.setNat64Prefix(p);
+        assertEquals(p, lp.getNat64Prefix());
+
+        p = new IpPrefix("2001:db8:a:b:1:2:3::/96");
+        lp.setNat64Prefix(p);
+        assertEquals(p, lp.getNat64Prefix());
+
+        p = new IpPrefix("2001:db8:a:b:1:2::/80");
+        try {
+            lp.setNat64Prefix(p);
+        } catch (IllegalArgumentException expected) {
+        }
+
+        p = new IpPrefix("64:ff9b::/64");
+        try {
+            lp.setNat64Prefix(p);
+        } catch (IllegalArgumentException expected) {
+        }
+
+        assertEquals(new IpPrefix("2001:db8:a:b:1:2:3::/96"), lp.getNat64Prefix());
+
+        lp.setNat64Prefix(null);
+        assertNull(lp.getNat64Prefix());
+    }
+
+    @Test
     public void testIsProvisioned() {
         LinkProperties lp4 = new LinkProperties();
         assertFalse("v4only:empty", lp4.isProvisioned());
@@ -815,7 +850,7 @@
     }
 
     @Test
-    public void testLinkPropertiesParcelable() {
+    public void testLinkPropertiesParcelable() throws Exception {
         LinkProperties source = new LinkProperties();
         source.setInterfaceName(NAME);
         // set 2 link addresses
@@ -833,6 +868,8 @@
 
         source.setMtu(MTU);
 
+        source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
+
         Parcel p = Parcel.obtain();
         source.writeToParcel(p, /* flags */ 0);
         p.setDataPosition(0);
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 0580df6..7783e10 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -115,6 +115,7 @@
         "optimize/MultiApkGenerator.cpp",
         "optimize/ResourceDeduper.cpp",
         "optimize/ResourceFilter.cpp",
+        "optimize/ResourcePathShortener.cpp",
         "optimize/VersionCollapser.cpp",
         "process/SymbolTable.cpp",
         "split/TableSplitter.cpp",
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index b353ff0..45719ef 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -223,8 +223,17 @@
     io::IFile* file = iterator->Next();
     std::string path = file->GetSource().path;
 
+    std::string output_path = path;
+    bool is_resource = path.find("res/") == 0;
+    if (is_resource) {
+      auto it = options.shortened_path_map.find(path);
+      if (it != options.shortened_path_map.end()) {
+        output_path = it->second;
+      }
+    }
+
     // Skip resources that are not referenced if requested.
-    if (path.find("res/") == 0 && referenced_resources.find(path) == referenced_resources.end()) {
+    if (is_resource && referenced_resources.find(output_path) == referenced_resources.end()) {
       if (context->IsVerbose()) {
         context->GetDiagnostics()->Note(DiagMessage()
                                         << "Removing resource '" << path << "' from APK.");
@@ -283,7 +292,8 @@
         return false;
       }
     } else {
-      if (!io::CopyFileToArchivePreserveCompression(context, file, path, writer)) {
+      if (!io::CopyFileToArchivePreserveCompression(
+              context, file, output_path, writer)) {
         return false;
       }
     }
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index 328b0be..2e6af18 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -41,6 +41,7 @@
 #include "optimize/MultiApkGenerator.h"
 #include "optimize/ResourceDeduper.h"
 #include "optimize/ResourceFilter.h"
+#include "optimize/ResourcePathShortener.h"
 #include "optimize/VersionCollapser.h"
 #include "split/TableSplitter.h"
 #include "util/Files.h"
@@ -52,6 +53,7 @@
 using ::android::ResTable_config;
 using ::android::StringPiece;
 using ::android::base::ReadFileToString;
+using ::android::base::WriteStringToFile;
 using ::android::base::StringAppendF;
 using ::android::base::StringPrintf;
 
@@ -143,6 +145,21 @@
       return 1;
     }
 
+    if (options_.shorten_resource_paths) {
+      ResourcePathShortener shortener(options_.table_flattener_options.shortened_path_map);
+      if (!shortener.Consume(context_, apk->GetResourceTable())) {
+        context_->GetDiagnostics()->Error(DiagMessage() << "failed shortening resource paths");
+        return 1;
+      }
+      if (options_.shortened_paths_map_path
+          && !WriteShortenedPathsMap(options_.table_flattener_options.shortened_path_map,
+                                      options_.shortened_paths_map_path.value())) {
+        context_->GetDiagnostics()->Error(DiagMessage()
+                                          << "failed to write shortened resource paths to file");
+        return 1;
+      }
+    }
+
     // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
     // equal to the minSdk.
     options_.split_constraints =
@@ -264,6 +281,15 @@
                                         ArchiveEntry::kAlign, writer);
   }
 
+  bool WriteShortenedPathsMap(const std::map<std::string, std::string> &path_map,
+                               const std::string &file_path) {
+    std::stringstream ss;
+    for (auto it = path_map.cbegin(); it != path_map.cend(); ++it) {
+      ss << it->first << " -> " << it->second << "\n";
+    }
+    return WriteStringToFile(ss.str(), file_path);
+  }
+
   OptimizeOptions options_;
   OptimizeContext* context_;
 };
diff --git a/tools/aapt2/cmd/Optimize.h b/tools/aapt2/cmd/Optimize.h
index d07305b..7f4a3ed 100644
--- a/tools/aapt2/cmd/Optimize.h
+++ b/tools/aapt2/cmd/Optimize.h
@@ -55,6 +55,12 @@
   // Set of artifacts to keep when generating multi-APK splits. If the list is empty, all artifacts
   // are kept and will be written as output.
   std::unordered_set<std::string> kept_artifacts;
+
+  // Whether or not to shorten resource paths in the APK.
+  bool shorten_resource_paths;
+
+  // Path to the output map of original resource paths to shortened paths.
+  Maybe<std::string> shortened_paths_map_path;
 };
 
 class OptimizeCommand : public Command {
@@ -101,6 +107,12 @@
     AddOptionalSwitch("--enable-resource-obfuscation",
         "Enables obfuscation of key string pool to single value",
         &options_.table_flattener_options.collapse_key_stringpool);
+    AddOptionalSwitch("--enable-resource-path-shortening",
+        "Enables shortening of the path of the resources inside the APK.",
+        &options_.shorten_resource_paths);
+    AddOptionalFlag("--resource-path-shortening-map",
+        "Path to output the map of old resource paths to shortened paths.",
+        &options_.shortened_paths_map_path);
     AddOptionalSwitch("-v", "Enables verbose logging", &verbose_);
   }
 
@@ -109,6 +121,9 @@
  private:
   OptimizeOptions options_;
 
+  bool WriteObfuscatedPathsMap(const std::map<std::string, std::string> &path_map,
+                               const std::string &file_path);
+
   Maybe<std::string> config_path_;
   Maybe<std::string> whitelist_path_;
   Maybe<std::string> resources_config_path_;
@@ -122,4 +137,4 @@
 
 }// namespace aapt
 
-#endif //AAPT2_OPTIMIZE_H
\ No newline at end of file
+#endif //AAPT2_OPTIMIZE_H
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index c496ff0..7d4c6f3 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -42,6 +42,19 @@
 
 namespace {
 
+static std::u16string strcpy16_dtoh(const char16_t* src, size_t len) {
+  size_t utf16_len = strnlen16(src, len);
+  if (utf16_len == 0) {
+    return {};
+  }
+  std::u16string dst;
+  dst.resize(utf16_len);
+  for (size_t i = 0; i < utf16_len; i++) {
+    dst[i] = util::DeviceToHost16(src[i]);
+  }
+  return dst;
+}
+
 // Visitor that converts a reference's resource ID to a resource name, given a mapping from
 // resource ID to resource name.
 class ReferenceIdToNameVisitor : public DescendingValueVisitor {
@@ -176,12 +189,8 @@
   }
 
   // Extract the package name.
-  size_t len = strnlen16((const char16_t*)package_header->name, arraysize(package_header->name));
-  std::u16string package_name;
-  package_name.resize(len);
-  for (size_t i = 0; i < len; i++) {
-    package_name[i] = util::DeviceToHost16(package_header->name[i]);
-  }
+  std::u16string package_name = strcpy16_dtoh((const char16_t*)package_header->name,
+                                              arraysize(package_header->name));
 
   ResourceTablePackage* package =
       table_->CreatePackage(util::Utf16ToUtf8(package_name), static_cast<uint8_t>(package_id));
@@ -435,6 +444,11 @@
   }
 
   auto overlayable = std::make_shared<Overlayable>();
+  overlayable->name = util::Utf16ToUtf8(strcpy16_dtoh((const char16_t*)header->name,
+                                                      arraysize(header->name)));
+  overlayable->actor = util::Utf16ToUtf8(strcpy16_dtoh((const char16_t*)header->actor,
+                                                       arraysize(header->name)));
+  overlayable->source = source_.WithLine(0);
 
   ResChunkPullParser parser(GetChunkData(chunk),
                             GetChunkDataLen(chunk));
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 931d57b..c4ecbaf 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -217,9 +217,10 @@
   size_t entry_count_ = 0;
 };
 
-struct PolicyChunk {
-  uint32_t policy_flags;
-  std::set<ResourceId> ids;
+struct OverlayableChunk {
+  std::string actor;
+  Source source;
+  std::map<OverlayableItem::PolicyFlags, std::set<ResourceId>> policy_ids;
 };
 
 class PackageFlattener {
@@ -421,8 +422,9 @@
     return sorted_entries;
   }
 
-  void FlattenOverlayable(BigBuffer* buffer) {
-    std::vector<PolicyChunk> policies;
+  bool FlattenOverlayable(BigBuffer* buffer) {
+    std::set<ResourceId> seen_ids;
+    std::map<std::string, OverlayableChunk> overlayable_chunks;
 
     CHECK(bool(package_->id)) << "package must have an ID set when flattening <overlayable>";
     for (auto& type : package_->types) {
@@ -433,79 +435,119 @@
           continue;
         }
 
-        OverlayableItem& overlayable = entry->overlayable_item.value();
-        uint32_t policy_flags = OverlayableItem::Policy::kNone;
-        if (overlayable.policies & OverlayableItem::Policy::kPublic) {
-          policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC;
-        }
-        if (overlayable.policies & OverlayableItem::Policy::kSystem) {
-          policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION;
-        }
-        if (overlayable.policies & OverlayableItem::Policy::kVendor) {
-          policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION;
-        }
-        if (overlayable.policies & OverlayableItem::Policy::kProduct) {
-          policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
-        }
-        if (overlayable.policies & OverlayableItem::Policy::kProductServices) {
-          policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION;
+        OverlayableItem& item = entry->overlayable_item.value();
+
+        // Resource ids should only appear once in the resource table
+        ResourceId id = android::make_resid(package_->id.value(), type->id.value(),
+                                            entry->id.value());
+        CHECK(seen_ids.find(id) == seen_ids.end())
+            << "multiple overlayable definitions found for resource "
+            << ResourceName(package_->name, type->type, entry->name).to_string();
+        seen_ids.insert(id);
+
+        // Find the overlayable chunk with the specified name
+        OverlayableChunk* overlayable_chunk = nullptr;
+        auto iter = overlayable_chunks.find(item.overlayable->name);
+        if (iter == overlayable_chunks.end()) {
+          OverlayableChunk chunk{item.overlayable->actor, item.overlayable->source};
+          overlayable_chunk =
+              &overlayable_chunks.insert({item.overlayable->name, chunk}).first->second;
+        } else {
+          OverlayableChunk& chunk = iter->second;
+          if (!(chunk.source == item.overlayable->source)) {
+            // The name of an overlayable set of resources must be unique
+            context_->GetDiagnostics()->Error(DiagMessage(item.overlayable->source)
+                                                  << "duplicate overlayable name"
+                                                  << item.overlayable->name << "'");
+            context_->GetDiagnostics()->Error(DiagMessage(chunk.source)
+                                                  << "previous declaration here");
+            return false;
+          }
+
+          CHECK(chunk.actor == item.overlayable->actor);
+          overlayable_chunk = &chunk;
         }
 
-        if (overlayable.policies == OverlayableItem::Policy::kNone) {
+        uint32_t policy_flags = 0;
+        if (item.policies == OverlayableItem::Policy::kNone) {
           // Encode overlayable entries defined without a policy as publicly overlayable
           policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC;
-        }
-
-        // Find the overlayable policy chunk with the same policies as the entry
-        PolicyChunk* policy_chunk = nullptr;
-        for (PolicyChunk& policy : policies) {
-          if (policy.policy_flags == policy_flags) {
-            policy_chunk = &policy;
-            break;
+        } else {
+          if (item.policies & OverlayableItem::Policy::kPublic) {
+            policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC;
+          }
+          if (item.policies & OverlayableItem::Policy::kSystem) {
+            policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION;
+          }
+          if (item.policies & OverlayableItem::Policy::kVendor) {
+            policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION;
+          }
+          if (item.policies & OverlayableItem::Policy::kProduct) {
+            policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
+          }
+          if (item.policies & OverlayableItem::Policy::kProductServices) {
+            policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION;
           }
         }
 
-        // Create a new policy chunk if an existing one with the same policy cannot be found
-        if (policy_chunk == nullptr) {
-          PolicyChunk p;
-          p.policy_flags = policy_flags;
-          policies.push_back(p);
-          policy_chunk = &policies.back();
+        auto policy = overlayable_chunk->policy_ids.find(policy_flags);
+        if (policy != overlayable_chunk->policy_ids.end()) {
+          policy->second.insert(id);
+        } else {
+          overlayable_chunk->policy_ids.insert(
+              std::make_pair(policy_flags, std::set<ResourceId>{id}));
         }
-
-        policy_chunk->ids.insert(android::make_resid(package_->id.value(), type->id.value(),
-                                                     entry->id.value()));
       }
     }
 
-    if (policies.empty()) {
-      // Only write the overlayable chunk if the APK has overlayable entries
-      return;
-    }
+    for (auto& overlayable_pair : overlayable_chunks) {
+      std::string name = overlayable_pair.first;
+      OverlayableChunk& overlayable = overlayable_pair.second;
 
-    ChunkWriter writer(buffer);
-    writer.StartChunk<ResTable_overlayable_header>(RES_TABLE_OVERLAYABLE_TYPE);
-
-    // Write each policy block for the overlayable
-    for (PolicyChunk& policy : policies) {
-      ChunkWriter policy_writer(buffer);
-      ResTable_overlayable_policy_header* policy_type =
-          policy_writer.StartChunk<ResTable_overlayable_policy_header>(
-              RES_TABLE_OVERLAYABLE_POLICY_TYPE);
-      policy_type->policy_flags = util::HostToDevice32(policy.policy_flags);
-      policy_type->entry_count = util::HostToDevice32(static_cast<uint32_t>(policy.ids.size()));
-
-      // Write the ids after the policy header
-      ResTable_ref* id_block = policy_writer.NextBlock<ResTable_ref>(policy.ids.size());
-      for (const ResourceId& id : policy.ids) {
-        id_block->ident = util::HostToDevice32(id.id);
-        id_block++;
+      // Write the header of the overlayable chunk
+      ChunkWriter overlayable_writer(buffer);
+      auto* overlayable_type =
+          overlayable_writer.StartChunk<ResTable_overlayable_header>(RES_TABLE_OVERLAYABLE_TYPE);
+      if (name.size() >= arraysize(overlayable_type->name)) {
+        diag_->Error(DiagMessage() << "overlayable name '" << name
+                                   << "' exceeds maximum length ("
+                                   << arraysize(overlayable_type->name)
+                                   << " utf16 characters)");
+        return false;
       }
+      strcpy16_htod(overlayable_type->name, arraysize(overlayable_type->name),
+                    util::Utf8ToUtf16(name));
 
-      policy_writer.Finish();
+      if (overlayable.actor.size() >= arraysize(overlayable_type->actor)) {
+        diag_->Error(DiagMessage() << "overlayable name '" << overlayable.actor
+                                   << "' exceeds maximum length ("
+                                   << arraysize(overlayable_type->actor)
+                                   << " utf16 characters)");
+        return false;
+      }
+      strcpy16_htod(overlayable_type->actor, arraysize(overlayable_type->actor),
+                    util::Utf8ToUtf16(overlayable.actor));
+
+      // Write each policy block for the overlayable
+      for (auto& policy_ids : overlayable.policy_ids) {
+        ChunkWriter policy_writer(buffer);
+        auto* policy_type = policy_writer.StartChunk<ResTable_overlayable_policy_header>(
+            RES_TABLE_OVERLAYABLE_POLICY_TYPE);
+        policy_type->policy_flags = util::HostToDevice32(static_cast<uint32_t>(policy_ids.first));
+        policy_type->entry_count = util::HostToDevice32(static_cast<uint32_t>(
+                                                            policy_ids.second.size()));
+        // Write the ids after the policy header
+        auto* id_block = policy_writer.NextBlock<ResTable_ref>(policy_ids.second.size());
+        for (const ResourceId& id : policy_ids.second) {
+          id_block->ident = util::HostToDevice32(id.id);
+          id_block++;
+        }
+        policy_writer.Finish();
+      }
+      overlayable_writer.Finish();
     }
 
-    writer.Finish();
+    return true;
   }
 
   bool FlattenTypeSpec(ResourceTableType* type, std::vector<ResourceEntry*>* sorted_entries,
diff --git a/tools/aapt2/format/binary/TableFlattener.h b/tools/aapt2/format/binary/TableFlattener.h
index 635cb21..71330e3 100644
--- a/tools/aapt2/format/binary/TableFlattener.h
+++ b/tools/aapt2/format/binary/TableFlattener.h
@@ -46,6 +46,9 @@
 
   // When true, sort the entries in the values string pool by priority and configuration.
   bool sort_stringpool_entries = true;
+
+  // Map from original resource paths to shortened resource paths.
+  std::map<std::string, std::string> shortened_path_map;
 };
 
 class TableFlattener : public IResourceTableConsumer {
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index a5fb6fd..18fecf6 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -657,36 +657,36 @@
 TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
   auto overlayable = std::make_shared<Overlayable>("TestName", "overlay://theme");
   std::string name_zero = "com.app.test:integer/overlayable_zero_item";
-  OverlayableItem overlayable_zero_item(overlayable);
-  overlayable_zero_item.policies |= OverlayableItem::Policy::kProduct;
-  overlayable_zero_item.policies |= OverlayableItem::Policy::kSystem;
-  overlayable_zero_item.policies |= OverlayableItem::Policy::kProductServices;
+  OverlayableItem overlayable_item_zero(overlayable);
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
 
   std::string name_one = "com.app.test:integer/overlayable_one_item";
-  OverlayableItem overlayable_one_item(overlayable);
-  overlayable_one_item.policies |= OverlayableItem::Policy::kPublic;
-  overlayable_one_item.policies |= OverlayableItem::Policy::kProductServices;
+  OverlayableItem overlayable_item_one(overlayable);
+  overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
+  overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
 
   std::string name_two = "com.app.test:integer/overlayable_two_item";
-  OverlayableItem overlayable_two_item(overlayable);
-  overlayable_two_item.policies |= OverlayableItem::Policy::kProduct;
-  overlayable_two_item.policies |= OverlayableItem::Policy::kSystem;
-  overlayable_two_item.policies |= OverlayableItem::Policy::kVendor;
+  OverlayableItem overlayable_item_two(overlayable);
+  overlayable_item_two.policies |= OverlayableItem::Policy::kProduct;
+  overlayable_item_two.policies |= OverlayableItem::Policy::kSystem;
+  overlayable_item_two.policies |= OverlayableItem::Policy::kVendor;
 
   std::string name_three = "com.app.test:integer/overlayable_three_item";
-  OverlayableItem overlayable_three_item(overlayable);
+  OverlayableItem overlayable_item_three(overlayable);
 
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
           .SetPackageId("com.app.test", 0x7f)
           .AddSimple(name_zero, ResourceId(0x7f020000))
-          .SetOverlayable(name_zero, overlayable_zero_item)
+          .SetOverlayable(name_zero, overlayable_item_zero)
           .AddSimple(name_one, ResourceId(0x7f020001))
-          .SetOverlayable(name_one, overlayable_one_item)
+          .SetOverlayable(name_one, overlayable_item_one)
           .AddSimple(name_two, ResourceId(0x7f020002))
-          .SetOverlayable(name_two, overlayable_two_item)
+          .SetOverlayable(name_two, overlayable_item_two)
           .AddSimple(name_three, ResourceId(0x7f020003))
-          .SetOverlayable(name_three, overlayable_three_item)
+          .SetOverlayable(name_three, overlayable_item_three)
           .Build();
 
   ResourceTable output_table;
@@ -724,6 +724,84 @@
   ASSERT_TRUE(search_result.value().entry->overlayable_item);
   overlayable_item = search_result.value().entry->overlayable_item.value();
   EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
+  EXPECT_EQ(overlayable_item.overlayable->name, "TestName");
+  EXPECT_EQ(overlayable_item.overlayable->actor, "overlay://theme");
+  EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
+}
+
+TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
+  auto group = std::make_shared<Overlayable>("TestName", "overlay://theme");
+  std::string name_zero = "com.app.test:integer/overlayable_zero";
+  OverlayableItem overlayable_item_zero(group);
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
+  overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
+
+  auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization");
+  std::string name_one = "com.app.test:integer/overlayable_one";
+  OverlayableItem overlayable_item_one(group_one);
+  overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
+  overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
+
+  std::string name_two = "com.app.test:integer/overlayable_two";
+  OverlayableItem overlayable_item_two(group);
+  overlayable_item_two.policies |= OverlayableItem::Policy::kProduct;
+  overlayable_item_two.policies |= OverlayableItem::Policy::kSystem;
+  overlayable_item_two.policies |= OverlayableItem::Policy::kVendor;
+
+  std::string name_three = "com.app.test:integer/overlayable_three";
+  OverlayableItem overlayable_item_three(group_one);
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.test", 0x7f)
+          .AddSimple(name_zero, ResourceId(0x7f020000))
+          .SetOverlayable(name_zero, overlayable_item_zero)
+          .AddSimple(name_one, ResourceId(0x7f020001))
+          .SetOverlayable(name_one, overlayable_item_one)
+          .AddSimple(name_two, ResourceId(0x7f020002))
+          .SetOverlayable(name_two, overlayable_item_two)
+          .AddSimple(name_three, ResourceId(0x7f020003))
+          .SetOverlayable(name_three, overlayable_item_three)
+          .Build();
+  ResourceTable output_table;
+  ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &output_table));
+  auto search_result = output_table.FindResource(test::ParseNameOrDie(name_zero));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  ASSERT_TRUE(search_result.value().entry->overlayable_item);
+  OverlayableItem& result_overlayable = search_result.value().entry->overlayable_item.value();
+  EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
+  EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
+  EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
+                                         | OverlayableItem::Policy::kProduct
+                                         | OverlayableItem::Policy::kProductServices);
+  search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  ASSERT_TRUE(search_result.value().entry->overlayable_item);
+  result_overlayable = search_result.value().entry->overlayable_item.value();
+  EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
+  EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
+  EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic
+                                         | OverlayableItem::Policy::kProductServices);
+  search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  ASSERT_TRUE(search_result.value().entry->overlayable_item);
+  result_overlayable = search_result.value().entry->overlayable_item.value();
+  EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
+  EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
+  EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
+                                         | OverlayableItem::Policy::kProduct
+                                         | OverlayableItem::Policy::kVendor);
+  search_result = output_table.FindResource(test::ParseNameOrDie(name_three));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  ASSERT_TRUE(search_result.value().entry->overlayable_item);
+  result_overlayable = search_result.value().entry->overlayable_item.value();
+  EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
+  EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
+  EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/optimize/ResourcePathShortener.cpp b/tools/aapt2/optimize/ResourcePathShortener.cpp
new file mode 100644
index 0000000..c5df3dd
--- /dev/null
+++ b/tools/aapt2/optimize/ResourcePathShortener.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "optimize/ResourcePathShortener.h"
+
+#include <math.h>
+#include <unordered_set>
+
+#include "androidfw/StringPiece.h"
+
+#include "ResourceTable.h"
+#include "ValueVisitor.h"
+
+
+static const std::string base64_chars =
+             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+             "abcdefghijklmnopqrstuvwxyz"
+             "0123456789-_";
+
+namespace aapt {
+
+ResourcePathShortener::ResourcePathShortener(
+    std::map<std::string, std::string>& path_map_out)
+    : path_map_(path_map_out) {
+}
+
+std::string ShortenFileName(const android::StringPiece& file_path, int output_length) {
+  std::size_t hash_num = std::hash<android::StringPiece>{}(file_path);
+  std::string result = "";
+  // Convert to (modified) base64 so that it is a proper file path.
+  for (int i = 0; i < output_length; i++) {
+    uint8_t sextet = hash_num & 0x3f;
+    hash_num >>= 6;
+    result += base64_chars[sextet];
+  }
+  return result;
+}
+
+
+// Calculate the optimal hash length such that an average of 10% of resources
+// collide in their shortened path.
+// Reference: http://matt.might.net/articles/counting-hash-collisions/
+int OptimalShortenedLength(int num_resources) {
+  int num_chars = 2;
+  double N = 64*64; // hash space when hash is 2 chars long
+  double max_collisions = num_resources * 0.1;
+  while (num_resources - N + N * pow((N - 1) / N, num_resources) > max_collisions) {
+    N *= 64;
+    num_chars++;
+  }
+  return num_chars;
+}
+
+std::string GetShortenedPath(const android::StringPiece& shortened_filename,
+    const android::StringPiece& extension, int collision_count) {
+  std::string shortened_path = "res/" + shortened_filename.to_string();
+  if (collision_count > 0) {
+    shortened_path += std::to_string(collision_count);
+  }
+  shortened_path += extension;
+  return shortened_path;
+}
+
+bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table) {
+  // used to detect collisions
+  std::unordered_set<std::string> shortened_paths;
+  std::unordered_set<FileReference*> file_refs;
+  for (auto& package : table->packages) {
+    for (auto& type : package->types) {
+      for (auto& entry : type->entries) {
+        for (auto& config_value : entry->values) {
+          FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
+          if (file_ref) {
+            file_refs.insert(file_ref);
+          }
+        }
+      }
+    }
+  }
+  int num_chars = OptimalShortenedLength(file_refs.size());
+  for (auto& file_ref : file_refs) {
+    android::StringPiece res_subdir, actual_filename, extension;
+    util::ExtractResFilePathParts(*file_ref->path, &res_subdir, &actual_filename, &extension);
+
+    std::string shortened_filename = ShortenFileName(*file_ref->path, num_chars);
+    int collision_count = 0;
+    std::string shortened_path = GetShortenedPath(shortened_filename, extension, collision_count);
+    while (shortened_paths.find(shortened_path) != shortened_paths.end()) {
+      collision_count++;
+      shortened_path = GetShortenedPath(shortened_filename, extension, collision_count);
+    }
+    shortened_paths.insert(shortened_path);
+    path_map_.insert({*file_ref->path, shortened_path});
+    file_ref->path = table->string_pool.MakeRef(shortened_path, file_ref->path.GetContext());
+  }
+  return true;
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/optimize/ResourcePathShortener.h b/tools/aapt2/optimize/ResourcePathShortener.h
new file mode 100644
index 0000000..f1074ef
--- /dev/null
+++ b/tools/aapt2/optimize/ResourcePathShortener.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
+#define AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
+
+#include <map>
+
+#include "android-base/macros.h"
+
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+
+class ResourceTable;
+
+// Maps resources in the apk to shortened paths.
+class ResourcePathShortener : public IResourceTableConsumer {
+ public:
+  explicit ResourcePathShortener(std::map<std::string, std::string>& path_map_out);
+
+  bool Consume(IAaptContext* context, ResourceTable* table) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResourcePathShortener);
+  std::map<std::string, std::string>& path_map_;
+};
+
+} // namespace aapt
+
+#endif  // AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
diff --git a/tools/aapt2/optimize/ResourcePathShortener_test.cpp b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
new file mode 100644
index 0000000..88cadc7
--- /dev/null
+++ b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "optimize/ResourcePathShortener.h"
+
+#include "ResourceTable.h"
+#include "test/Test.h"
+
+using ::aapt::test::GetValue;
+using ::testing::Not;
+using ::testing::NotNull;
+using ::testing::Eq;
+
+namespace aapt {
+
+TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddFileReference("android:drawable/xmlfile", "res/drawables/xmlfile.xml")
+          .AddFileReference("android:drawable/xmlfile2", "res/drawables/xmlfile2.xml")
+          .AddString("android:string/string", "res/should/still/be/the/same.png")
+          .Build();
+
+  std::map<std::string, std::string> path_map;
+  ASSERT_TRUE(ResourcePathShortener(path_map).Consume(context.get(), table.get()));
+
+  // Expect that the path map is populated
+  ASSERT_THAT(path_map.find("res/drawables/xmlfile.xml"), Not(Eq(path_map.end())));
+  ASSERT_THAT(path_map.find("res/drawables/xmlfile2.xml"), Not(Eq(path_map.end())));
+
+  // The file paths were changed
+  EXPECT_THAT(path_map.at("res/drawables/xmlfile.xml"), Not(Eq("res/drawables/xmlfile.xml")));
+  EXPECT_THAT(path_map.at("res/drawables/xmlfile2.xml"), Not(Eq("res/drawables/xmlfile2.xml")));
+
+  // Different file paths should remain different
+  EXPECT_THAT(path_map["res/drawables/xmlfile.xml"],
+              Not(Eq(path_map["res/drawables/xmlfile2.xml"])));
+
+  FileReference* ref =
+      GetValue<FileReference>(table.get(), "android:drawable/xmlfile");
+  ASSERT_THAT(ref, NotNull());
+  // The map correctly points to the new location of the file
+  EXPECT_THAT(path_map["res/drawables/xmlfile.xml"], Eq(*ref->path));
+
+  // Strings should not be affected, only file paths
+  EXPECT_THAT(
+      *GetValue<String>(table.get(), "android:string/string")->value,
+              Eq("res/should/still/be/the/same.png"));
+  EXPECT_THAT(path_map.find("res/should/still/be/the/same.png"), Eq(path_map.end()));
+}
+
+}   // namespace aapt
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index acf1f1e..d1fe43e 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -297,7 +297,7 @@
 class V2LineParser(object):
     __slots__ = ["tokenized", "current", "len"]
 
-    MODIFIERS = set("public protected internal private abstract default static final transient volatile synchronized".split())
+    MODIFIERS = set("public protected internal private abstract default static final transient volatile synchronized native operator sealed strictfp infix inline suspend vararg".split())
     JAVA_LANG_TYPES = set("AbstractMethodError AbstractStringBuilder Appendable ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException AssertionError AutoCloseable Boolean BootstrapMethodError Byte Character CharSequence Class ClassCastException ClassCircularityError ClassFormatError ClassLoader ClassNotFoundException Cloneable CloneNotSupportedException Comparable Compiler Deprecated Double Enum EnumConstantNotPresentException Error Exception ExceptionInInitializerError Float FunctionalInterface IllegalAccessError IllegalAccessException IllegalArgumentException IllegalMonitorStateException IllegalStateException IllegalThreadStateException IncompatibleClassChangeError IndexOutOfBoundsException InheritableThreadLocal InstantiationError InstantiationException Integer InternalError InterruptedException Iterable LinkageError Long Math NegativeArraySizeException NoClassDefFoundError NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException NullPointerException Number NumberFormatException Object OutOfMemoryError Override Package package-info.java Process ProcessBuilder ProcessEnvironment ProcessImpl Readable ReflectiveOperationException Runnable Runtime RuntimeException RuntimePermission SafeVarargs SecurityException SecurityManager Short StackOverflowError StackTraceElement StrictMath String StringBuffer StringBuilder StringIndexOutOfBoundsException SuppressWarnings System Thread ThreadDeath ThreadGroup ThreadLocal Throwable TypeNotPresentException UNIXProcess UnknownError UnsatisfiedLinkError UnsupportedClassVersionError UnsupportedOperationException VerifyError VirtualMachineError Void".split())
 
     def __init__(self, raw):
@@ -355,7 +355,7 @@
         self.parse_eof()
 
     def parse_into_field(self, field):
-        kind = self.parse_token("field")
+        kind = self.parse_one_of("field", "property")
         field.split = [kind]
         annotations = self.parse_annotations()
         if "@Deprecated" in annotations:
@@ -442,13 +442,19 @@
         return None
 
     def parse_type(self):
+        self.parse_annotations()
         type = self.parse_token()
+        if type[-1] == '.':
+            self.parse_annotations()
+            type += self.parse_token()
         if type in V2LineParser.JAVA_LANG_TYPES:
             type = "java.lang." + type
         self.parse_matching_paren("<", ">")
         while True:
             t = self.lookahead()
-            if t == "[]":
+            if t == "@":
+                self.parse_annotation()
+            elif t == "[]":
                 type += self.parse_token()
             elif self.parse_kotlin_nullability() is not None:
                 pass  # discard nullability for now
@@ -478,17 +484,23 @@
             self.parse_token(",")
 
     def parse_arg(self):
+        self.parse_if("vararg")  # kotlin vararg
         self.parse_annotations()
         type = self.parse_arg_type()
         l = self.lookahead()
         if l != "," and l != ")":
-            self.parse_token()  # kotlin argument name
+            if self.lookahead() != '=':
+                self.parse_token()  # kotlin argument name
             if self.parse_if('='): # kotlin default value
-                (self.parse_matching_paren('(', ')') or
-                 self.parse_matching_paren('{', '}') or
-                 self.parse_token() and self.parse_matching_paren('(', ')'))
+                self.parse_expression()
         return type
 
+    def parse_expression(self):
+        while not self.lookahead() in [')', ',', ';']:
+            (self.parse_matching_paren('(', ')') or
+            self.parse_matching_paren('{', '}') or
+            self.parse_token())
+
     def parse_throws(self):
         ret = []
         if self.parse_if("throws"):
@@ -516,7 +528,7 @@
 
     def parse_annotation_default(self):
         if self.parse_if("default"):
-            self.parse_value()
+            self.parse_expression()
 
     def parse_value(self):
         if self.lookahead() == "{":
@@ -599,7 +611,7 @@
             clazz.ctors.append(Method(clazz, line, raw, blame, sig_format=sig_format))
         elif raw.startswith("    method"):
             clazz.methods.append(Method(clazz, line, raw, blame, sig_format=sig_format))
-        elif raw.startswith("    field"):
+        elif raw.startswith("    field") or raw.startswith("    property"):
             clazz.fields.append(Field(clazz, line, raw, blame, sig_format=sig_format))
         elif raw.startswith("  }") and clazz:
             yield clazz
@@ -942,7 +954,7 @@
             else:
                 error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable")
 
-        if not "static" in f.split:
+        if "static" not in f.split and "property" not in f.split:
             if not re.match("[a-z]([a-zA-Z]+)?", f.name):
                 error(clazz, f, "S1", "Non-static fields must be named using myField style")
 
@@ -1650,7 +1662,7 @@
         binary.add(op)
 
     for m in clazz.methods:
-        if 'static' in m.split:
+        if 'static' in m.split or 'operator' in m.split:
             continue
 
         # https://kotlinlang.org/docs/reference/operator-overloading.html#unary-prefix-operators
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
index 081e98d..fde61a9 100644
--- a/tools/apilint/apilint_test.py
+++ b/tools/apilint/apilint_test.py
@@ -225,11 +225,12 @@
         self.assertEquals('pkg.SuppressLint', cls.fullname)
 
     def test_parse_method(self):
-        m = self._method("method @Deprecated public static <T> Class<T>[][] name("
+        m = self._method("method @Deprecated public static native <T> Class<T>[][] name("
                          + "Class<T[]>[][], Class<T[][][]>[][]...) throws Exception, T;")
         self.assertTrue('static' in m.split)
         self.assertTrue('public' in m.split)
         self.assertTrue('method' in m.split)
+        self.assertTrue('native' in m.split)
         self.assertTrue('deprecated' in m.split)
         self.assertEquals('java.lang.Class[][]', m.typ)
         self.assertEquals('name', m.name)
@@ -248,6 +249,7 @@
         self._method('method abstract String category() default "";', cls=cls)
         self._method('method abstract boolean deepExport() default false;', cls=cls)
         self._method('method abstract ViewDebug.FlagToString[] flagMapping() default {};', cls=cls)
+        self._method('method abstract ViewDebug.FlagToString[] flagMapping() default (double)java.lang.Float.NEGATIVE_INFINITY;', cls=cls)
 
     def test_parse_string_field(self):
         f = self._field('field @Deprecated public final String SOME_NAME = "value";')
@@ -286,5 +288,44 @@
         self._method("method <T> T name(T a = 1, T b = A(1), Lambda f = { false }, N? n = null, "
                          + """double c = (1/0), float d = 1.0f, String s = "heyo", char c = 'a');""")
 
+    def test_kotlin_operator(self):
+        self._method('method public operator void unaryPlus(androidx.navigation.NavDestination);')
+        self._method('method public static operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);')
+        self._method('method public static operator <T> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);')
+
+    def test_kotlin_property(self):
+        self._field('property public VM value;')
+        self._field('property public final String? action;')
+
+    def test_kotlin_varargs(self):
+        self._method('method public void error(int p = "42", Integer int2 = "null", int p1 = "42", vararg String args);')
+
+    def test_kotlin_default_values(self):
+        self._method('method public void foo(String! = null, String! = "Hello World", int = 42);')
+        self._method('method void method(String, String firstArg = "hello", int secondArg = "42", String thirdArg = "world");')
+        self._method('method void method(String, String firstArg = "hello", int secondArg = "42");')
+        self._method('method void method(String, String firstArg = "hello");')
+        self._method('method void edit(android.Type, boolean commit = false, Function1<? super Editor,kotlin.Unit> action);')
+        self._method('method <K, V> LruCache<K,V> lruCache(int maxSize, Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, Function1<? extends V> create = { (V)null }, Function4<kotlin.Unit> onEntryRemoved = { _, _, _, _ ->  });')
+        self._method('method android.Bitmap? drawToBitmap(android.View, android.Config config = android.graphics.Bitmap.Config.ARGB_8888);')
+        self._method('method void emptyLambda(Function0<kotlin.Unit> sizeOf = {});')
+        self._method('method void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);')
+        self._method('method void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);')
+        self._method('method void method3(String str, int p, int int2 = double(int) + str.length);')
+        self._method('method void print(test.pkg.Foo foo = test.pkg.Foo());')
+
+    def test_type_use_annotation(self):
+        self._method('method public static int codePointAt(char @NonNull [], int);')
+        self._method('method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();')
+
+        m = self._method('method @NonNull public java.lang.annotation.@NonNull Annotation @NonNull [] getAnnotations();')
+        self.assertEquals('java.lang.annotation.Annotation[]', m.typ)
+
+        m = self._method('method @NonNull public abstract java.lang.annotation.@NonNull Annotation @NonNull [] @NonNull [] getParameterAnnotations();')
+        self.assertEquals('java.lang.annotation.Annotation[][]', m.typ)
+
+        m = self._method('method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);')
+        self.assertEquals('java.lang.String[]', m.typ)
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/signedconfig/prod_public.pem b/tools/signedconfig/prod_public.pem
new file mode 100644
index 0000000..8c10215
--- /dev/null
+++ b/tools/signedconfig/prod_public.pem
@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+lky6wKyGL6lE1VrD0YTMHwb0Xwc
++tzC8MvnrzVxodvTpVY/jV7V+Zktcx+pry43XPABFRXtbhTo+qykhyBA1g==
+-----END PUBLIC KEY-----
+
diff --git a/tools/signedconfig/verify_b64.sh b/tools/signedconfig/verify_b64.sh
index 8e1f58c..a4ac6a8 100755
--- a/tools/signedconfig/verify_b64.sh
+++ b/tools/signedconfig/verify_b64.sh
@@ -7,4 +7,30 @@
 # The arg values can be taken from the debug log for SignedConfigService when verbose logging is
 # enabled.
 
-openssl dgst -sha256 -verify $(dirname $0)/debug_public.pem -signature <(echo $2 | base64 -d) <(echo $1 | base64 -d)
+function verify() {
+  D=${1}
+  S=${2}
+  K=${3}
+  echo Trying ${K}
+  openssl dgst -sha256 -verify $(dirname $0)/${K} -signature <(echo ${S} | base64 -d) <(echo ${D} | base64 -d)
+}
+
+
+PROD_KEY_NAME=prod_public.pem
+DEBUG_KEY_NAME=debug_public.pem
+SIGNATURE="$2"
+DATA="$1"
+
+echo DATA: ${DATA}
+echo SIGNATURE: ${SIGNATURE}
+
+if verify "${DATA}" "${SIGNATURE}" "${PROD_KEY_NAME}"; then
+  echo Verified with ${PROD_KEY_NAME}
+  exit 0
+fi
+
+if verify "${DATA}" "${SIGNATURE}" "${DEBUG_KEY_NAME}"; then
+  echo Verified with ${DEBUG_KEY_NAME}
+  exit 0
+fi
+exit 1
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index af5ad51..840af5d 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -93,12 +93,22 @@
     private int mRssi;
 
     /**
-     * Link speed in Mbps
+     * The unit in which links speeds are expressed.
      */
     public static final String LINK_SPEED_UNITS = "Mbps";
     private int mLinkSpeed;
 
     /**
+     * Tx(transmit) Link speed in Mbps
+     */
+    private int mTxLinkSpeed;
+
+    /**
+     * Rx(receive) Link speed in Mbps
+     */
+    private int mRxLinkSpeed;
+
+    /**
      * Frequency in MHz
      */
     public static final String FREQUENCY_UNITS = "MHz";
@@ -192,6 +202,8 @@
         setNetworkId(-1);
         setRssi(INVALID_RSSI);
         setLinkSpeed(-1);
+        setTxLinkSpeedMbps(-1);
+        setRxLinkSpeedMbps(-1);
         setFrequency(-1);
         setMeteredHint(false);
         setEphemeral(false);
@@ -219,6 +231,8 @@
             mNetworkId = source.mNetworkId;
             mRssi = source.mRssi;
             mLinkSpeed = source.mLinkSpeed;
+            mTxLinkSpeed = source.mTxLinkSpeed;
+            mRxLinkSpeed = source.mRxLinkSpeed;
             mFrequency = source.mFrequency;
             mIpAddress = source.mIpAddress;
             mMacAddress = source.mMacAddress;
@@ -313,7 +327,7 @@
 
     /**
      * Returns the current link speed in {@link #LINK_SPEED_UNITS}.
-     * @return the link speed.
+     * @return the link speed or -1 if there is no valid value.
      * @see #LINK_SPEED_UNITS
      */
     public int getLinkSpeed() {
@@ -323,7 +337,39 @@
     /** @hide */
     @UnsupportedAppUsage
     public void setLinkSpeed(int linkSpeed) {
-        this.mLinkSpeed = linkSpeed;
+        mLinkSpeed = linkSpeed;
+    }
+
+    /**
+     * Returns the current transmit link speed in Mbps.
+     * @return the Tx link speed or -1 if there is no valid value.
+     */
+    public int getTxLinkSpeedMbps() {
+        return mTxLinkSpeed;
+    }
+
+    /**
+     * Update the last transmitted packet bit rate in Mbps.
+     * @hide
+     */
+    public void setTxLinkSpeedMbps(int txLinkSpeed) {
+        mTxLinkSpeed = txLinkSpeed;
+    }
+
+    /**
+     * Returns the current receive link speed in Mbps.
+     * @return the Rx link speed or -1 if there is no valid value.
+     */
+    public int getRxLinkSpeedMbps() {
+        return mRxLinkSpeed;
+    }
+
+    /**
+     * Update the last received packet bit rate in Mbps.
+     * @hide
+     */
+    public void setRxLinkSpeedMbps(int rxLinkSpeed) {
+        mRxLinkSpeed = rxLinkSpeed;
     }
 
     /**
@@ -529,17 +575,19 @@
         StringBuffer sb = new StringBuffer();
         String none = "<none>";
 
-        sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid).
-            append(", BSSID: ").append(mBSSID == null ? none : mBSSID).
-            append(", MAC: ").append(mMacAddress == null ? none : mMacAddress).
-            append(", Supplicant state: ").
-            append(mSupplicantState == null ? none : mSupplicantState).
-            append(", RSSI: ").append(mRssi).
-            append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS).
-            append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS).
-            append(", Net ID: ").append(mNetworkId).
-            append(", Metered hint: ").append(mMeteredHint).
-            append(", score: ").append(Integer.toString(score));
+        sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid)
+                .append(", BSSID: ").append(mBSSID == null ? none : mBSSID)
+                .append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
+                .append(", Supplicant state: ")
+                .append(mSupplicantState == null ? none : mSupplicantState)
+                .append(", RSSI: ").append(mRssi)
+                .append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
+                .append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
+                .append(", Rx Link speed: ").append(mRxLinkSpeed).append(LINK_SPEED_UNITS)
+                .append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS)
+                .append(", Net ID: ").append(mNetworkId)
+                .append(", Metered hint: ").append(mMeteredHint)
+                .append(", score: ").append(Integer.toString(score));
         return sb.toString();
     }
 
@@ -553,6 +601,8 @@
         dest.writeInt(mNetworkId);
         dest.writeInt(mRssi);
         dest.writeInt(mLinkSpeed);
+        dest.writeInt(mTxLinkSpeed);
+        dest.writeInt(mRxLinkSpeed);
         dest.writeInt(mFrequency);
         if (mIpAddress != null) {
             dest.writeByte((byte)1);
@@ -593,6 +643,8 @@
                 info.setNetworkId(in.readInt());
                 info.setRssi(in.readInt());
                 info.setLinkSpeed(in.readInt());
+                info.setTxLinkSpeedMbps(in.readInt());
+                info.setRxLinkSpeedMbps(in.readInt());
                 info.setFrequency(in.readInt());
                 if (in.readByte() == 1) {
                     try {