Merge changes from topic "heads-up-ambient-inflation"

* changes:
  Fix heads up views freeing too early.
  Inflate ambient + heads up view as necessary
diff --git a/Android.bp b/Android.bp
index 7e71bdf..f9b60e6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -614,6 +614,7 @@
         ":netd_aidl",
         ":vold_aidl",
         ":installd_aidl",
+        ":dumpstate_aidl",
 
         "lowpan/java/android/net/lowpan/ILowpanEnergyScanCallback.aidl",
         "lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl",
@@ -660,6 +661,7 @@
         include_dirs: [
             "system/update_engine/binder_bindings",
             "frameworks/native/aidl/binder",
+            "frameworks/native/cmds/dumpstate/binder",
             "frameworks/av/camera/aidl",
             "frameworks/av/media/libaudioclient/aidl",
             "frameworks/native/aidl/gui",
@@ -682,9 +684,6 @@
 
     no_framework_libs: true,
     libs: [
-        "conscrypt",
-        "okhttp",
-        "bouncycastle",
         "ext",
     ],
 
@@ -706,6 +705,7 @@
         "android.hardware.radio-V1.0-java",
         "android.hardware.radio-V1.3-java",
         "android.hardware.usb.gadget-V1.0-java",
+        "netd_aidl_interface-java",
     ],
 
     // Loaded with System.loadLibrary by android.view.textclassifier
@@ -835,7 +835,6 @@
         "cmds/statsd/src/**/*.proto",
         "core/proto/**/*.proto",
         "libs/incident/proto/**/*.proto",
-        "proto/src/stats_enums.proto",
     ],
     proto: {
         include_dirs: ["external/protobuf/src"],
@@ -873,7 +872,6 @@
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/proto/android/os/**/*.proto",
-        "proto/src/stats_enums.proto",
     ],
     // Protos have lots of MissingOverride and similar.
     errorprone: {
@@ -899,7 +897,6 @@
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
-        "proto/src/stats_enums.proto",
     ],
 
     target: {
@@ -1096,14 +1093,13 @@
      "-federationapi SupportLib $(location current/support-api.txt) "
 
 framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+     "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
      "-overview $(location core/java/overview.html) " +
      // Federate Support Library references against local API file.
      "-federate SupportLib https://developer.android.com " +
      "-federationapi SupportLib $(location current/support-api.txt) "
 
 framework_docs_only_libs = [
-    "conscrypt",
-    "bouncycastle",
     "voip-common",
     "android.test.mock",
     "android-support-annotations",
@@ -1183,7 +1179,8 @@
 
 doc_defaults {
     name: "framework-docs-default",
-    libs: framework_docs_only_libs,
+    libs: framework_docs_only_libs +
+         ["stub-annotations"],
     html_dirs: [
         "docs/html",
     ],
@@ -1580,7 +1577,6 @@
         "core/java/org/apache/http/params/CoreConnectionPNames.java",
         "core/java/org/apache/http/params/HttpConnectionParams.java",
         "core/java/org/apache/http/params/HttpParams.java",
-        "core/java/android/net/http/HttpResponseCache.java",
         "core/java/android/net/http/SslCertificate.java",
         "core/java/android/net/http/SslError.java",
         "core/java/com/android/internal/util/HexDump.java",
diff --git a/api/current.txt b/api/current.txt
index 3a44d34..c710729 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -17,6 +17,7 @@
     field public static final java.lang.String ACCESS_NOTIFICATION_POLICY = "android.permission.ACCESS_NOTIFICATION_POLICY";
     field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
     field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
+    field public static final java.lang.String ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION";
     field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
     field public static final java.lang.String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
@@ -168,6 +169,7 @@
 
   public static final class Manifest.permission_group {
     ctor public Manifest.permission_group();
+    field public static final java.lang.String ACTIVITY_RECOGNITION = "android.permission-group.ACTIVITY_RECOGNITION";
     field public static final java.lang.String CALENDAR = "android.permission-group.CALENDAR";
     field public static final java.lang.String CALL_LOG = "android.permission-group.CALL_LOG";
     field public static final java.lang.String CAMERA = "android.permission-group.CAMERA";
@@ -15405,6 +15407,69 @@
 
 }
 
+package android.graphics.text {
+
+  public class LineBreaker {
+    method public android.graphics.text.LineBreaker.Result computeLineBreaks(android.graphics.text.MeasuredText, android.graphics.text.LineBreaker.ParagraphConstraints, int);
+    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
+    field public static final int BREAK_STRATEGY_HIGH_QUALITY = 1; // 0x1
+    field public static final int BREAK_STRATEGY_SIMPLE = 0; // 0x0
+    field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
+    field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
+    field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
+  }
+
+  public static class LineBreaker.Builder {
+    ctor public LineBreaker.Builder();
+    method public android.graphics.text.LineBreaker build();
+    method public android.graphics.text.LineBreaker.Builder setBreakStrategy(int);
+    method public android.graphics.text.LineBreaker.Builder setHyphenationFrequency(int);
+    method public android.graphics.text.LineBreaker.Builder setIndents(int[]);
+    method public android.graphics.text.LineBreaker.Builder setJustified(int);
+  }
+
+  public static class LineBreaker.ParagraphConstraints {
+    ctor public LineBreaker.ParagraphConstraints();
+    method public int getDefaultTabStop();
+    method public float getFirstWidth();
+    method public int getFirstWidthLineCount();
+    method public int[] getTabStops();
+    method public float getWidth();
+    method public void setIndent(float, int);
+    method public void setTabStops(int[], int);
+    method public void setWidth(float);
+  }
+
+  public static class LineBreaker.Result {
+    method public float getLineAscent(int);
+    method public int getLineBreakOffset(int);
+    method public int getLineCount();
+    method public float getLineDescent(int);
+    method public int getLineHyphenEdit(int);
+    method public float getLineWidth(int);
+    method public boolean hasLineTab(int);
+  }
+
+  public class MeasuredText {
+    method public void getBounds(int, int, android.graphics.Rect);
+    method public float getCharWidthAt(int);
+    method public char[] getChars();
+    method public float getWidth(int, int);
+  }
+
+  public static class MeasuredText.Builder {
+    ctor public MeasuredText.Builder(char[]);
+    method public android.graphics.text.MeasuredText.Builder addReplacementRun(android.graphics.Paint, int, int, float);
+    method public android.graphics.text.MeasuredText.Builder addStyleRun(android.graphics.Paint, int, int, boolean);
+    method public android.graphics.text.MeasuredText build();
+    method public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
+    method public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean);
+  }
+
+}
+
 package android.hardware {
 
   public deprecated class Camera {
@@ -32540,7 +32605,7 @@
 
   public class Build {
     ctor public Build();
-    method public static java.util.List<android.os.Build.Partition> getPartitions();
+    method public static java.util.List<android.os.Build.Partition> getFingerprintedPartitions();
     method public static java.lang.String getRadioVersion();
     method public static java.lang.String getSerial();
     field public static final java.lang.String BOARD;
@@ -32571,9 +32636,9 @@
 
   public static class Build.Partition {
     ctor public Build.Partition();
+    method public long getBuildTimeMillis();
     method public java.lang.String getFingerprint();
     method public java.lang.String getName();
-    method public long getTimeMillis();
     field public static final java.lang.String PARTITION_NAME_SYSTEM = "system";
   }
 
@@ -43323,7 +43388,7 @@
     field public static final int PROTOCOL_IPV6 = 1; // 0x1
     field public static final int PROTOCOL_PPP = 3; // 0x3
     field public static final int TYPE_CBS = 128; // 0x80
-    field public static final int TYPE_DEFAULT = 1; // 0x1
+    field public static final int TYPE_DEFAULT = 17; // 0x11
     field public static final int TYPE_DUN = 8; // 0x8
     field public static final int TYPE_EMERGENCY = 512; // 0x200
     field public static final int TYPE_FOTA = 32; // 0x20
@@ -48025,6 +48090,7 @@
 
   public class TouchDelegate {
     ctor public TouchDelegate(android.graphics.Rect, android.view.View);
+    method public android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo getTouchDelegateInfo();
     method public boolean onTouchEvent(android.view.MotionEvent);
     field public static final int ABOVE = 1; // 0x1
     field public static final int BELOW = 2; // 0x2
@@ -50007,6 +50073,7 @@
     method public int getTextSelectionEnd();
     method public int getTextSelectionStart();
     method public java.lang.CharSequence getTooltipText();
+    method public android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo getTouchDelegateInfo();
     method public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter();
     method public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore();
     method public java.lang.String getViewIdResourceName();
@@ -50097,6 +50164,7 @@
     method public void setTextEntryKey(boolean);
     method public void setTextSelection(int, int);
     method public void setTooltipText(java.lang.CharSequence);
+    method public void setTouchDelegateInfo(android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo);
     method public void setTraversalAfter(android.view.View);
     method public void setTraversalAfter(android.view.View, int);
     method public void setTraversalBefore(android.view.View);
@@ -50223,6 +50291,16 @@
     field public static final int RANGE_TYPE_PERCENT = 2; // 0x2
   }
 
+  public static final class AccessibilityNodeInfo.TouchDelegateInfo implements android.os.Parcelable {
+    ctor public AccessibilityNodeInfo.TouchDelegateInfo(java.util.Map<android.graphics.Region, android.view.View>);
+    method public int describeContents();
+    method public android.graphics.Region getRegionAt(int);
+    method public int getRegionCount();
+    method public android.view.accessibility.AccessibilityNodeInfo getTargetForRegion(android.graphics.Region);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo> CREATOR;
+  }
+
   public abstract class AccessibilityNodeProvider {
     ctor public AccessibilityNodeProvider();
     method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index ac8fc9c..0a89ffb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -119,6 +119,7 @@
     field public static final java.lang.String MOUNT_FORMAT_FILESYSTEMS = "android.permission.MOUNT_FORMAT_FILESYSTEMS";
     field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
     field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
+    field public static final java.lang.String NETWORK_SETUP_WIZARD = "android.permission.NETWORK_SETUP_WIZARD";
     field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
     field public static final java.lang.String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
     field public static final java.lang.String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
@@ -221,7 +222,7 @@
   }
 
   public static final class R.dimen {
-    field public static final int config_restricted_icon_size = 17104903; // 0x1050007
+    field public static final int config_restrictedIconSize = 17104903; // 0x1050007
   }
 
   public static final class R.drawable {
@@ -234,12 +235,12 @@
   }
 
   public static final class R.string {
-    field public static final int config_feedback_intent_extra_key = 17039391; // 0x104001f
-    field public static final int config_feedback_intent_name_key = 17039392; // 0x1040020
-    field public static final int config_help_intent_extra_key = 17039389; // 0x104001d
-    field public static final int config_help_intent_name_key = 17039390; // 0x104001e
-    field public static final int config_help_package_name_key = 17039387; // 0x104001b
-    field public static final int config_help_package_name_value = 17039388; // 0x104001c
+    field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f
+    field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020
+    field public static final int config_helpIntentExtraKey = 17039389; // 0x104001d
+    field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
+    field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
+    field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
   }
 
   public static final class R.style {
@@ -1150,7 +1151,8 @@
     method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
     method public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence);
-    method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String);
+    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);
     method public abstract void setUpdateAvailable(java.lang.String, boolean);
     method public abstract boolean updateIntentVerificationStatusAsUser(java.lang.String, int, int);
     method public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
@@ -1244,6 +1246,22 @@
     field public int requestRes;
   }
 
+  public final class SuspendDialogInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.SuspendDialogInfo> CREATOR;
+  }
+
+  public static final class SuspendDialogInfo.Builder {
+    ctor public SuspendDialogInfo.Builder();
+    method public android.content.pm.SuspendDialogInfo build();
+    method public android.content.pm.SuspendDialogInfo.Builder setIcon(int);
+    method public android.content.pm.SuspendDialogInfo.Builder setMessage(java.lang.String);
+    method public android.content.pm.SuspendDialogInfo.Builder setMessage(int);
+    method public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonText(int);
+    method public android.content.pm.SuspendDialogInfo.Builder setTitle(int);
+  }
+
 }
 
 package android.content.pm.dex {
@@ -1280,14 +1298,6 @@
 
 }
 
-package android.graphics.drawable {
-
-  public final class Icon implements android.os.Parcelable {
-    method public static android.graphics.drawable.Icon createWithResource(android.content.res.Resources, int);
-  }
-
-}
-
 package android.hardware {
 
   public final class Sensor {
@@ -3189,6 +3199,7 @@
   public class ConnectivityManager {
     method public java.lang.String getCaptivePortalServerUrl();
     method public boolean isTetheringSupported();
+    method public void setAirplaneMode(boolean);
     method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
     method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
     method public void stopTethering(int);
@@ -4136,7 +4147,6 @@
 
   public class UserManager {
     method public void clearSeedAccountData();
-    method public int[] getProfileIds(int, boolean);
     method public java.lang.String getSeedAccountName();
     method public android.os.PersistableBundle getSeedAccountOptions();
     method public java.lang.String getSeedAccountType();
@@ -4201,8 +4211,8 @@
   }
 
   public static final class PermissionManager.SplitPermissionInfo {
-    method public java.lang.String[] getNewPermissions();
-    method public java.lang.String getRootPermission();
+    method public java.util.List<java.lang.String> getNewPermissions();
+    method public java.lang.String getSplitPermission();
     method public int getTargetSdk();
   }
 
@@ -5287,6 +5297,7 @@
     method public int getRejectCause();
     method public int getTransportType();
     method public boolean isEmergencyEnabled();
+    method public boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationState> CREATOR;
     field public static final int DOMAIN_CS = 1; // 0x1
@@ -5374,6 +5385,8 @@
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
     field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
     field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
+    field public static final android.net.Uri ENHANCED_4G_ENABLED_CONTENT_URI;
+    field public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
   }
 
   public final class SubscriptionPlan implements android.os.Parcelable {
@@ -6653,7 +6666,7 @@
 package android.view {
 
   public abstract class Window {
-    method public void addPrivateFlags(int);
+    method public void addSystemFlags(int);
   }
 
   public abstract interface WindowManager implements android.view.ViewManager {
@@ -6663,7 +6676,10 @@
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
     method public final long getUserActivityTimeout();
     method public final void setUserActivityTimeout(long);
-    field public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
+    field public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
+  }
+
+  public static abstract class WindowManager.LayoutParams.SystemFlags implements java.lang.annotation.Annotation {
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 937c266..463c9d3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1609,6 +1609,10 @@
     method public void writeToParcelNoRecycle(android.os.Parcel, int);
   }
 
+  public static final class AccessibilityNodeInfo.TouchDelegateInfo implements android.os.Parcelable {
+    method public long getAccessibilityIdForRegion(android.graphics.Region);
+  }
+
   public final class AccessibilityWindowInfo implements android.os.Parcelable {
     method public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
   }
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 4091d95..6a9e8a1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -39,7 +39,8 @@
     GET_DATA_CALLED = 4,
     ADB_DUMP = 5,
     CONFIG_RESET = 6,
-    STATSCOMPANION_DIED = 7
+    STATSCOMPANION_DIED = 7,
+    TERMINATION_SIGNAL_RECEIVED = 8
 };
 
 class StatsLogProcessor : public ConfigListener {
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8da2d44..fb6f8c8 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -867,6 +867,13 @@
     mConfigManager->Startup();
 }
 
+void StatsService::Terminate() {
+    ALOGI("StatsService::Terminating");
+    if (mProcessor != nullptr) {
+        mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED);
+    }
+}
+
 void StatsService::OnLogEvent(LogEvent* event) {
     mProcessor->OnLogEvent(event);
     if (mShellSubscriber != nullptr) {
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 1f1d782..cbf3429 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -84,6 +84,11 @@
     void Startup();
 
     /**
+     * Called when terminiation signal received.
+     */
+    void Terminate();
+
+    /**
      * Called by LogReader when there's a log event to process.
      */
     virtual void OnLogEvent(LogEvent* event);
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index a2a03b1..453bf7e 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -36,8 +36,8 @@
 // exclusive state field, and any number of primary key fields.
 // For example,
 // message UidProcessStateChanged {
-//    optional int32 uid = 1 [(stateFieldOption).option = PRIMARY];
-//    optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
+//    optional int32 uid = 1 [(state_field_option).option = PRIMARY];
+//    optional android.app.ProcessStateEnum state = 2 [(state_field_option).option = EXCLUSIVE];
 //  }
 // Each of this UidProcessStateChanged atom represents a state change for a specific uid.
 // A new state automatically overrides the previous state.
@@ -46,16 +46,16 @@
 // the primary key.
 // For example:
 // message ThreadStateChanged {
-//    optional int32 pid = 1  [(stateFieldOption).option = PRIMARY];
-//    optional int32 tid = 2  [(stateFieldOption).option = PRIMARY];
-//    optional int32 state = 3 [(stateFieldOption).option = EXCLUSIVE];
+//    optional int32 pid = 1  [(state_field_option).option = PRIMARY];
+//    optional int32 tid = 2  [(state_field_option).option = PRIMARY];
+//    optional int32 state = 3 [(state_field_option).option = EXCLUSIVE];
 // }
 //
 // Sometimes, there is no primary key field, when the state is GLOBAL.
 // For example,
 //
 // message ScreenStateChanged {
-//    optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
+//    optional android.view.DisplayStateEnum state = 1 [(state_field_option).option = EXCLUSIVE];
 // }
 //
 // Only fields of primary types can be annotated. AttributionNode cannot be primary keys (and they
@@ -66,7 +66,7 @@
 
 extend google.protobuf.FieldOptions {
     // Flags to decorate an atom that presents a state change.
-    optional StateAtomFieldOption stateFieldOption = 50000;
+    optional StateAtomFieldOption state_field_option = 50000;
 
     // Flags to decorate the uid fields in an atom.
     optional bool is_uid = 50001 [default = false];
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9d83afd..4604510 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -26,12 +26,11 @@
 import "frameworks/base/core/proto/android/bluetooth/enums.proto";
 import "frameworks/base/core/proto/android/os/enums.proto";
 import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/service/procstats_enum.proto";
+import "frameworks/base/core/proto/android/stats/enums.proto";
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
-import "frameworks/base/proto/src/stats_enums.proto";
-import "frameworks/base/core/proto/android/service/procstats.proto";
-import "frameworks/base/core/proto/android/internal/powerprofile.proto";
 
 /**
  * The master atom class. This message defines all of the available
@@ -142,6 +141,8 @@
         BatteryHealthSnapshot battery_health_snapshot = 91;
         SlowIo slow_io = 92;
         BatteryCausedShutdown battery_caused_shutdown = 93;
+        PhoneServiceStateChanged phone_service_state_changed = 94;
+        PhoneStateChanged phone_state_changed = 95;
     }
 
     // Pulled events will start at field 10000.
@@ -273,7 +274,7 @@
  */
 message ScreenStateChanged {
     // New screen state, from frameworks/base/core/proto/android/view/enums.proto.
-    optional android.view.DisplayStateEnum state = 1 [(stateFieldOption).option = EXCLUSIVE];
+    optional android.view.DisplayStateEnum state = 1 [(state_field_option).option = EXCLUSIVE];
 }
 
 /**
@@ -284,10 +285,10 @@
  *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
  */
 message UidProcessStateChanged {
-    optional int32 uid = 1 [(stateFieldOption).option = PRIMARY, (is_uid) = true];
+    optional int32 uid = 1 [(state_field_option).option = PRIMARY, (is_uid) = true];
 
     // The state, from frameworks/base/core/proto/android/app/enums.proto.
-    optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
+    optional android.app.ProcessStateEnum state = 2 [(state_field_option).option = EXCLUSIVE];
 }
 
 /**
@@ -319,7 +320,7 @@
         ASLEEP = 1;
         AWAKE = 2;
     }
-    optional State state = 1 [(stateFieldOption).option = EXCLUSIVE];
+    optional State state = 1 [(state_field_option).option = EXCLUSIVE];
 }
 
 /**
@@ -338,7 +339,7 @@
         CRITICAL = 4;   // critical memory.
 
     }
-    optional State factor = 1 [(stateFieldOption).option = EXCLUSIVE];
+    optional State factor = 1 [(state_field_option).option = EXCLUSIVE];
 }
 
 /**
@@ -637,7 +638,7 @@
 
     // The type (level) of the wakelock; e.g. a partial wakelock or a full wakelock.
     // From frameworks/base/core/proto/android/os/enums.proto.
-    optional android.os.WakeLockLevelEnum level = 2;
+    optional android.os.WakeLockLevelEnum type = 2;
 
     // The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
     optional string tag = 3;
@@ -1030,20 +1031,20 @@
     // Bit mask of color capabilities of the screen.
     // Contains information about the color gamut and hdr mode of the screen.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#colorMode
-    optional int32 colorMode = 1;
+    optional int32 color_mode = 1;
 
     // The target screen density being rendered to.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#densityDpi
-    optional int32 densityDpi = 2;
+    optional int32 density_dpi = 2;
 
     // Current user preference for the scaling factor for fonts,
     // relative to the base density scaling.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#fontScale
-    optional float fontScale = 3;
+    optional float font_scale = 3;
 
     // Flag indicating whether the hard keyboard is hidden.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#hardKeyboardHidden
-    optional int32 hardKeyboardHidden = 4;
+    optional int32 hard_keyboard_hidden = 4;
 
     // The type of keyboard attached to the device.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#keyboard
@@ -1051,7 +1052,7 @@
 
     // Flag indicating whether any keyboard is available. Takes soft keyboards into account.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#keyboardHidden
-    optional int32 keyboardHideen = 6;
+    optional int32 keyboard_hidden = 6;
 
     // IMSI MCC (Mobile Country Code), corresponding to mcc resource qualifier.
     // 0 if undefined.
@@ -1070,7 +1071,7 @@
 
     // Flag indicating whether the navigation is available.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#navigationHidden
-    optional int32 navigationHidden = 10;
+    optional int32 navigation_hidden = 10;
 
     // Overall orientation of the screen.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#orientation
@@ -1078,24 +1079,24 @@
 
     // The current height of the available screen space, in dp units.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#screenHeightDp
-    optional int32 screenHeightDp = 12;
+    optional int32 screen_height_dp = 12;
 
     // Bit mask of overall layout of the screen.
     // Contains information about screen size, whether the screen is wider/taller
     // than normal, whether the screen layout is right-tl-left or left-to-right,
     // and whether the screen has a rounded shape.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#screenLayout
-    optional int32 screenLayout = 13;
+    optional int32 screen_layout = 13;
 
     // Current width of the available screen space, in dp units.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#screenWidthDp
-    optional int32 screenWidthDp = 14;
+    optional int32 screen_width_dp = 14;
 
     // The smallest screen size an application will see in normal operation.
     // This is the smallest value of both screenWidthDp and screenHeightDp
     // in portrait and landscape.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#smallestScreenWidthDp
-    optional int32 smallestScreenWidthDp = 15;
+    optional int32 smallest_screen_width_dp = 15;
 
     // The type of touch screen attached to the device.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#touchscreen
@@ -1106,7 +1107,7 @@
     // Eg: NORMAL, DESK, CAR, TELEVISION, WATCH, VR_HEADSET
     // Also contains information about whether the device is in night mode.
     // See: https://d.android.com/reference/android/content/res/Configuration.html#uiMode
-    optional int32 uiMode = 17;
+    optional int32 ui_mode = 17;
 }
 
 
@@ -1193,7 +1194,7 @@
     // Eg. Airplane mode, crash, application request.
     optional android.bluetooth.EnableDisableReasonEnum reason = 3;
     // If the reason is an application request, this will be the package name.
-    optional string pkgName = 4;
+    optional string pkg_name = 4;
 }
 
 /**
@@ -1342,7 +1343,7 @@
     }
     optional BatterySnapshotType type = 1;
     // Temperature, in 1/10ths of degree C.
-    optional int32 temperature_deci_celcius = 2;
+    optional int32 temperature_deci_celsius = 2;
     // Voltage Battery Voltage, in microVolts.
     optional int32 voltage_micro_volt = 3;
     // Current Battery current, in microAmps.
@@ -1406,6 +1407,33 @@
     optional android.telephony.SignalStrengthEnum signal_strength = 1;
 }
 
+
+/**
+ * Logs when the phone state, sim state or signal strength changes
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message PhoneServiceStateChanged {
+    optional android.telephony.ServiceStateEnum state = 1;
+    optional android.telephony.SimStateEnum sim_state = 2;
+    optional android.telephony.SignalStrengthEnum signal_strength = 3;
+}
+
+/**
+ * Logs when the phone becomes on or off.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/com/android/internal/os/TelephonyRegistry.java
+ */
+message PhoneStateChanged {
+    enum State {
+        OFF = 0;
+        ON = 1;
+    }
+    optional State state = 1;
+}
+
 /**
  * Logs that a setting was updated.
  * Logged from:
@@ -1843,10 +1871,10 @@
     optional string activity_name = 3;
 
     // # of page-faults
-    optional int64 pgfault = 4;
+    optional int64 page_fault = 4;
 
     // # of major page-faults
-    optional int64 pgmajfault = 5;
+    optional int64 page_major_fault = 5;
 
     // RSS
     optional int64 rss_in_bytes = 6;
@@ -1886,13 +1914,13 @@
     optional string process_name = 2;
 
     // oom adj score.
-    optional int32 oom_score = 3;
+    optional int32 oom_adj_score = 3;
 
     // # of page-faults
-    optional int64 pgfault = 4;
+    optional int64 page_fault = 4;
 
     // # of major page-faults
-    optional int64 pgmajfault = 5;
+    optional int64 page_major_fault = 5;
 
     // RSS
     optional int64 rss_in_bytes = 6;
@@ -1912,7 +1940,7 @@
  */
 message AppDied {
     // timestamp(elapsedRealtime) of record creation
-    optional uint64 timestamp_millis = 1 [(stateFieldOption).option = EXCLUSIVE];
+    optional uint64 timestamp_millis = 1 [(state_field_option).option = EXCLUSIVE];
 }
 
 /**
@@ -1923,7 +1951,7 @@
     optional int32 uid = 1 [(is_uid) = true];
 
     // An event_id indicates the type of event.
-    optional android.os.statsd.EventType event_id = 2;
+    optional android.stats.EventType event_id = 2;
 }
 
 /**
@@ -2154,7 +2182,7 @@
 
     optional int32 version = 3;
 
-    optional int64 time = 4;
+    optional int64 time_micros = 4;
 }
 
 /**
@@ -2218,11 +2246,11 @@
     // stack reported state
     // TODO: replace this with proto enum
     optional int32 stack_state = 2;
-    // tx time in ms
+    // tx time in millis
     optional uint64 controller_tx_time_millis = 3;
-    // rx time in ms
+    // rx time in millis
     optional uint64 controller_rx_time_millis = 4;
-    // idle time in ms
+    // idle time in millis
     optional uint64 controller_idle_time_millis = 5;
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 controller_energy_used = 6;
@@ -2234,9 +2262,9 @@
 message ModemActivityInfo {
     // timestamp(wall clock) of record creation
     optional uint64 timestamp_millis = 1;
-    // sleep time in ms.
+    // sleep time in millis.
     optional uint64 sleep_time_millis = 2;
-    // idle time in ms
+    // idle time in millis
     optional uint64 controller_idle_time_millis = 3;
     /**
      * Tx power index
@@ -2271,11 +2299,11 @@
     optional uint64 timestamp_millis = 1;
     // bluetooth stack state
     optional int32 bluetooth_stack_state = 2;
-    // tx time in ms
+    // tx time in millis
     optional uint64 controller_tx_time_millis = 3;
-    // rx time in ms
+    // rx time in millis
     optional uint64 controller_rx_time_millis = 4;
-    // idle time in ms
+    // idle time in millis
     optional uint64 controller_idle_time_millis = 5;
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 energy_used = 6;
@@ -2292,13 +2320,13 @@
     optional string process_name = 2;
 
     // oom adj score.
-    optional int32 oom_score = 3;
+    optional int32 oom_adj_score = 3;
 
     // # of page-faults
-    optional int64 pgfault = 4;
+    optional int64 page_fault = 4;
 
     // # of major page-faults
-    optional int64 pgmajfault = 5;
+    optional int64 page_major_fault = 5;
 
     // RSS
     optional int64 rss_in_bytes = 6;
@@ -2380,7 +2408,7 @@
  *   frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
  */
 message RemainingBatteryCapacity {
-    optional int32 charge_uAh = 1;
+    optional int32 charge_micro_ampere_hour = 1;
 }
 
 /**
@@ -2389,7 +2417,7 @@
  *   frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
  */
 message FullBatteryCapacity {
-    optional int32 capacity_uAh = 1;
+    optional int32 capacity_micro_ampere_hour = 1;
 }
 
 /**
@@ -2399,7 +2427,7 @@
  */
 message BatteryVoltage {
     // The voltage of the battery, in millivolts.
-    optional int32 voltage_mV = 1;
+    optional int32 voltage_millivolt = 1;
 }
 
 /**
@@ -2417,7 +2445,7 @@
     optional string sensor_name = 2;
 
     // Temperature in tenths of a degree C.
-    optional int32 temperature_dC = 3;
+    optional int32 temperature_deci_celsius = 3;
 }
 
 /**
@@ -2527,8 +2555,7 @@
     // recorded_message_count.
     //
     // If recorded_message_count is different than message_count, it means data
-    // collection has been sampled. All the fields below will be sampled in this
-    // case.
+    // collection has been sampled. The fields below will be sampled in this case.
     optional int64 recorded_message_count = 7;
 
     // Total latency of all processed messages.
@@ -2544,6 +2571,32 @@
 
     // True if the screen was interactive PowerManager#isInteractive at the end of the call.
     optional bool screen_interactive = 10;
+
+    // Max recorded CPU usage of all processed messages.
+    optional int64 recorded_max_cpu_micros = 11;
+
+    // Max recorded latency of all processed messages.
+    optional int64 recorded_max_latency_micros = 12;
+
+    // Total number of messages we tracked the dispatching delay for. If we
+    // collected data for all the messages, message_count will be equal to
+    // recorded_delay_message_count.
+    //
+    // If recorded_delay_message_count is different than message_count, it means data
+    // collection has been sampled or/and not all messages specified the target dispatch time.
+    // The fields below will be sampled in this case.
+    optional int64 recorded_delay_message_count = 13;
+
+    // Total dispatching delay of all processed messages.
+    // Calculated as a difference between the target dispatching time (Message.when)
+    // and the actual dispatching time.
+    // Average can be computed using recorded_total_delay_millis / recorded_delay_message_count.
+    optional int64 recorded_total_delay_millis = 14;
+
+    // Max dispatching delay of all processed messages.
+    // Calculated as a difference between the target dispatching time (Message.when)
+    // and the actual dispatching time.
+    optional int64 recorded_max_delay_millis = 15;
 }
 
 /**
@@ -2662,11 +2715,288 @@
     optional int32 num_fingerprints = 2;
 }
 
+message AggStats {
+    optional int64 min = 1;
+
+    optional int64 average = 2;
+
+    optional int64 max = 3;
+}
+
+message ProcessStatsStateProto {
+    optional android.service.procstats.ScreenState screen_state = 1;
+
+    optional android.service.procstats.MemoryState memory_state = 2;
+
+    // this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
+    // and not frameworks/base/core/java/android/app/ActivityManager.java
+    optional android.service.procstats.ProcessState process_state = 3;
+
+    // Millisecond uptime duration spent in this state
+    optional int64 duration_millis = 4;
+
+    // Millisecond elapsed realtime duration spent in this state
+    optional int64 realtime_duration_millis = 9;
+
+    // # of samples taken
+    optional int32 sample_size = 5;
+
+    // PSS is memory reserved for this process
+    optional AggStats pss = 6;
+
+    // USS is memory shared between processes, divided evenly for accounting
+    optional AggStats uss = 7;
+
+    // RSS is memory resident for this process
+    optional AggStats rss = 8;
+}
+
+// Next Tag: 7
+message ProcessStatsProto {
+    // Name of process.
+    optional string process = 1;
+
+    // Uid of the process.
+    optional int32 uid = 2;
+
+    // Information about how often kills occurred
+    message Kill {
+        // Count of excessive CPU kills
+        optional int32 cpu = 1;
+
+        // Count of kills when cached
+        optional int32 cached = 2;
+
+        // PSS stats during cached kill
+        optional AggStats cached_pss = 3;
+    }
+    optional Kill kill = 3;
+
+    // Time and memory spent in various states.
+    repeated ProcessStatsStateProto states = 5;
+
+    // Total time process has been running...  screen_state, memory_state, and process_state
+    // will not be set.
+    optional ProcessStatsStateProto total_running_state = 6;
+}
+
+message PackageServiceOperationStatsProto {
+    // Operate enum: Started, Foreground, Bound, Executing
+    optional android.service.procstats.ServiceOperationState operation = 1;
+
+    // Number of times the service was in this operation.
+    optional int32 count = 2;
+
+    // Information about a state the service can be in.
+    message StateStats {
+        // Screen state enum.
+        optional android.service.procstats.ScreenState screen_state = 1;
+        // Memory state enum.
+        optional android.service.procstats.MemoryState memory_state = 2;
+
+        // duration in milliseconds.
+        optional int64 duration_millis = 3;
+        // Millisecond elapsed realtime duration spent in this state
+        optional int64 realtime_duration_millis = 4;
+    }
+    repeated StateStats state_stats = 3;
+}
+
+message PackageServiceStatsProto {
+    // Name of service component.
+    optional string service_name = 1;
+
+    // The operation stats.
+    // The package_name, package_uid, package_version, service_name will not be set to save space.
+    repeated PackageServiceOperationStatsProto operation_stats = 2;
+}
+
+message PackageAssociationSourceProcessStatsProto {
+    // Uid of the process.
+    optional int32 process_uid = 1;
+    // Process name.
+    optional string process_name = 2;
+
+    // Total count of the times this association appeared.
+    optional int32 total_count = 3;
+
+    // Millisecond uptime total duration this association was around.
+    optional int64 total_duration_millis = 4;
+
+    // Total count of the times this association became actively impacting its target process.
+    optional int32 active_count = 5;
+
+    // Information on one source in this association.
+    message StateStats {
+        // Process state enum.
+        optional android.service.procstats.ProcessState process_state = 1;
+        // Millisecond uptime duration spent in this state
+        optional int64 duration_millis = 2;
+        // Millisecond elapsed realtime duration spent in this state
+        optional int64 realtime_duration_mmillis = 3;
+    }
+    repeated StateStats active_state_stats = 6;
+}
+
+message PackageAssociationProcessStatsProto {
+    // Name of the target component.
+    optional string component_name = 1;
+    // Information on one source in this association.
+    repeated PackageAssociationSourceProcessStatsProto sources = 2;
+}
+
+
+message ProcessStatsPackageProto {
+    // Name of package.
+    optional string package = 1;
+
+    // Uid of the package.
+    optional int32 uid = 2;
+
+    // Version of the package.
+    optional int64 version = 3;
+
+    // Stats for each process running with the package loaded in to it.
+    repeated ProcessStatsProto process_stats = 4;
+
+    // Stats for each of the package's services.
+    repeated PackageServiceStatsProto service_stats = 5;
+
+    // Stats for each association with the package.
+    repeated PackageAssociationProcessStatsProto association_stats = 6;
+}
+
+message ProcessStatsSectionProto {
+    // Elapsed realtime at start of report.
+    optional int64 start_realtime_millis = 1;
+
+    // Elapsed realtime at end of report.
+    optional int64 end_realtime_millis = 2;
+
+    // CPU uptime at start of report.
+    optional int64 start_uptime_millis = 3;
+
+    // CPU uptime at end of report.
+    optional int64 end_uptime_millis = 4;
+
+    // System runtime library. e.g. "libdvm.so", "libart.so".
+    optional string runtime = 5;
+
+    // whether kernel reports swapped pss.
+    optional bool has_swapped_pss = 6;
+
+    // Data completeness. e.g. "complete", "partial", shutdown", or "sysprops".
+    enum Status {
+        STATUS_UNKNOWN = 0;
+        STATUS_COMPLETE = 1;
+        STATUS_PARTIAL = 2;
+        STATUS_SHUTDOWN = 3;
+        STATUS_SYSPROPS = 4;
+    }
+    repeated Status status = 7;
+
+    // Stats for each process.
+    repeated ProcessStatsProto process_stats = 8;
+
+    // Stats for each package.
+    repeated ProcessStatsPackageProto package_stats = 9;
+}
+
 /**
  * Pulled from ProcessStatsService.java
  */
 message ProcStats {
-    optional android.service.procstats.ProcessStatsSectionProto proc_stats_section = 1;
+    optional ProcessStatsSectionProto proc_stats_section = 1;
+}
+
+message PowerProfileProto {
+    optional double cpu_suspend = 1;
+
+    optional double cpu_idle = 2;
+
+    optional double cpu_active = 3;
+
+    message CpuCluster {
+        optional int32 id = 1;
+        optional double cluster_power = 2;
+        optional int32 cores = 3;
+        repeated int64 speed = 4;
+        repeated double core_power = 5;
+    }
+
+    repeated CpuCluster cpu_cluster = 40;
+
+    optional double wifi_scan = 4;
+
+    optional double wifi_on = 5;
+
+    optional double wifi_active = 6;
+
+    optional double wifi_controller_idle = 7;
+
+    optional double wifi_controller_rx = 8;
+
+    optional double wifi_controller_tx = 9;
+
+    repeated double wifi_controller_tx_levels = 10;
+
+    optional double wifi_controller_operating_voltage = 11;
+
+    optional double bluetooth_controller_idle = 12;
+
+    optional double bluetooth_controller_rx = 13;
+
+    optional double bluetooth_controller_tx = 14;
+
+    optional double bluetooth_controller_operating_voltage = 15;
+
+    optional double modem_controller_sleep = 16;
+
+    optional double modem_controller_idle = 17;
+
+    optional double modem_controller_rx = 18;
+
+    repeated double modem_controller_tx = 19;
+
+    optional double modem_controller_operating_voltage = 20;
+
+    optional double gps_on = 21;
+
+    repeated double gps_signal_quality_based = 22;
+
+    optional double gps_operating_voltage = 23;
+
+    optional double bluetooth_on = 24;
+
+    optional double bluetooth_active = 25;
+
+    optional double bluetooth_at_cmd = 26;
+
+    optional double ambient_display = 27;
+
+    optional double screen_on = 28;
+
+    optional double radio_on = 29;
+
+    optional double radio_scanning = 30;
+
+    optional double radio_active = 31;
+
+    optional double screen_full = 32;
+
+    optional double audio = 33;
+
+    optional double video = 34;
+
+    optional double flashlight = 35;
+
+    optional double memory = 36;
+
+    optional double camera = 37;
+
+    optional double wifi_batched_scan = 38;
+
+    optional double battery_capacity = 39;
 }
 
 /**
@@ -2674,5 +3004,5 @@
  * Pulled from PowerProfile.java
  */
 message PowerProfile {
-    optional com.android.internal.os.PowerProfileProto power_profile_proto = 1;
-}
\ No newline at end of file
+    optional PowerProfileProto power_profile = 1;
+}
diff --git a/cmds/statsd/src/hash.cpp b/cmds/statsd/src/hash.cpp
index c501c9f..543a748 100644
--- a/cmds/statsd/src/hash.cpp
+++ b/cmds/statsd/src/hash.cpp
@@ -16,6 +16,10 @@
 
 #include "hash.h"
 
+#ifndef FALLTHROUGH_INTENDED
+#define FALLTHROUGH_INTENDED [[fallthrough]]
+#endif
+
 namespace android {
 namespace os {
 namespace statsd {
@@ -67,8 +71,10 @@
   switch (n) {
     case 3:
       h ^= ByteAs32(data[2]) << 16;
+      FALLTHROUGH_INTENDED;
     case 2:
       h ^= ByteAs32(data[1]) << 8;
+      FALLTHROUGH_INTENDED;
     case 1:
       h ^= ByteAs32(data[0]);
       h *= m;
@@ -104,16 +110,22 @@
   switch (n) {
     case 7:
       h ^= ByteAs64(data[6]) << 48;
+      FALLTHROUGH_INTENDED;
     case 6:
       h ^= ByteAs64(data[5]) << 40;
+      FALLTHROUGH_INTENDED;
     case 5:
       h ^= ByteAs64(data[4]) << 32;
+      FALLTHROUGH_INTENDED;
     case 4:
       h ^= ByteAs64(data[3]) << 24;
+      FALLTHROUGH_INTENDED;
     case 3:
       h ^= ByteAs64(data[2]) << 16;
+      FALLTHROUGH_INTENDED;
     case 2:
       h ^= ByteAs64(data[1]) << 8;
+      FALLTHROUGH_INTENDED;
     case 1:
       h ^= ByteAs64(data[0]);
       h *= m;
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index a5dac08..6b8c12a 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -46,6 +46,27 @@
     sp<StatsService> service;
 };
 
+
+sp<StatsService> gStatsService = nullptr;
+
+void sigHandler(int sig) {
+    if (gStatsService != nullptr) {
+        gStatsService->Terminate();
+    }
+}
+
+void registerSigHandler()
+{
+    struct sigaction sa;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = sigHandler;
+    sigaction(SIGHUP, &sa, nullptr);
+    sigaction(SIGINT, &sa, nullptr);
+    sigaction(SIGQUIT, &sa, nullptr);
+    sigaction(SIGTERM, &sa, nullptr);
+}
+
 int main(int /*argc*/, char** /*argv*/) {
     // Set up the looper
     sp<Looper> looper(Looper::prepare(0 /* opts */));
@@ -60,23 +81,25 @@
     ::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
 
     // Create the service
-    sp<StatsService> service = new StatsService(looper);
-    if (defaultServiceManager()->addService(String16("stats"), service) != 0) {
+    gStatsService = new StatsService(looper);
+    if (defaultServiceManager()->addService(String16("stats"), gStatsService) != 0) {
         ALOGE("Failed to add service as AIDL service");
         return -1;
     }
 
-    auto ret = service->registerAsService();
+    auto ret = gStatsService->registerAsService();
     if (ret != ::android::OK) {
         ALOGE("Failed to add service as HIDL service");
         return 1; // or handle error
     }
 
-    service->sayHiToStatsCompanion();
+    registerSigHandler();
 
-    service->Startup();
+    gStatsService->sayHiToStatsCompanion();
 
-    sp<StatsSocketListener> socketListener = new StatsSocketListener(service);
+    gStatsService->Startup();
+
+    sp<StatsSocketListener> socketListener = new StatsSocketListener(gStatsService);
 
         ALOGI("using statsd socket");
         // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index ab0b23c..10ed7f3 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -271,6 +271,7 @@
       ADB_DUMP = 5;
       CONFIG_RESET = 6;
       STATSCOMPANION_DIED = 7;
+      TERMINATION_SIGNAL_RECEIVED = 8;
   }
   optional DumpReportReason dump_report_reason = 8;
 
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 5b6f167..5729feb 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -152,7 +152,7 @@
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
@@ -161,7 +161,7 @@
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(2).atom_size());
     EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
@@ -170,7 +170,7 @@
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(3).atom_size());
     EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
@@ -179,7 +179,7 @@
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(3).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(3).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(4).atom_size());
     EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
@@ -188,7 +188,7 @@
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(4).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(4).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(5).atom_size());
     EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
@@ -197,7 +197,7 @@
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(5).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_deci_celsius(), 0);
 }
 
 TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) {
@@ -275,7 +275,7 @@
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
@@ -284,7 +284,7 @@
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(2, data.bucket_info(2).atom_size());
     EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
@@ -295,9 +295,9 @@
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0);
     EXPECT_TRUE(data.bucket_info(2).atom(1).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(2).atom(1).temperature().temperature_deci_celsius(), 0);
 }
 
 
@@ -378,7 +378,7 @@
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(0).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(0).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(1).atom_size());
     EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
@@ -387,7 +387,7 @@
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(1).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(1).atom(0).temperature().temperature_deci_celsius(), 0);
 
     EXPECT_EQ(1, data.bucket_info(2).atom_size());
     EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
@@ -396,7 +396,7 @@
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
     EXPECT_TRUE(data.bucket_info(2).atom(0).temperature().sensor_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_dc(), 0);
+    EXPECT_GT(data.bucket_info(2).atom(0).temperature().temperature_deci_celsius(), 0);
 
 }
 
diff --git a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
index 2b7da6a..4f4dd01 100644
--- a/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
+++ b/cmds/statsd/tools/dogfood/src/com/android/statsd/dogfood/MainActivity.java
@@ -319,7 +319,7 @@
         int[] uids = new int[]{mUids[id]};
         String[] tags = new String[]{"acquire"};
         StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags,
-                StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name,
+                StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name,
                 StatsLog.WAKELOCK_STATE_CHANGED__STATE__ACQUIRE);
         StringBuilder sb = new StringBuilder();
         sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0)
@@ -335,7 +335,7 @@
         int[] uids = new int[]{mUids[id]};
         String[] tags = new String[]{"release"};
         StatsLog.write(StatsLog.WAKELOCK_STATE_CHANGED, uids, tags,
-                StatsLog.WAKELOCK_STATE_CHANGED__LEVEL__PARTIAL_WAKE_LOCK, name,
+                StatsLog.WAKELOCK_STATE_CHANGED__TYPE__PARTIAL_WAKE_LOCK, name,
                 StatsLog.WAKELOCK_STATE_CHANGED__STATE__RELEASE);
         StringBuilder sb = new StringBuilder();
         sb.append("StagsLog.write(10, ").append(mUids[id]).append(", ").append(0)
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 6af34f9..b71274c 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -523,7 +523,6 @@
 Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
 Landroid/net/IConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String;
 Landroid/net/IConnectivityManager;->reportInetCondition(II)V
-Landroid/net/IConnectivityManager;->setAirplaneMode(Z)V
 Landroid/net/IConnectivityManager;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V
 Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
 Landroid/net/INetworkPolicyListener$Stub;-><init>()V
@@ -2216,6 +2215,7 @@
 Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
 Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
 Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
+Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
 Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
 Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
 Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
@@ -2791,6 +2791,7 @@
 Ljavax/net/ssl/SSLSocketFactory;->createSocket(Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket;
 Ljavax/net/ssl/SSLSocketFactory;->defaultSocketFactory:Ljavax/net/ssl/SSLSocketFactory;
 Llibcore/icu/ICU;->addLikelySubtags(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/io/Libcore;->os:Llibcore/io/Os;
 Llibcore/io/Memory;->peekByte(J)B
 Llibcore/io/Memory;->peekByteArray(J[BII)V
 Llibcore/io/Memory;->peekInt(JZ)I
diff --git a/core/java/android/app/AppDetailsActivity.java b/core/java/android/app/AppDetailsActivity.java
new file mode 100644
index 0000000..cd36e63
--- /dev/null
+++ b/core/java/android/app/AppDetailsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Helper activity that forwards you to app details page.
+ *
+ * @hide
+ */
+public class AppDetailsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        intent.setData(android.net.Uri.fromParts("package", getPackageName(), null));
+        startActivity(intent);
+        finish();
+    }
+}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 264029b..fcd9a05 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -55,6 +55,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.SharedLibraryInfo;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VersionedPackage;
 import android.content.pm.dex.ArtManager;
@@ -85,6 +86,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.IconDrawableFactory;
 import android.util.LauncherIcons;
@@ -2255,9 +2257,19 @@
     public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
             PersistableBundle appExtras, PersistableBundle launcherExtras,
             String dialogMessage) {
+        final SuspendDialogInfo dialogInfo = !TextUtils.isEmpty(dialogMessage)
+                ? new SuspendDialogInfo.Builder().setMessage(dialogMessage).build()
+                : null;
+        return setPackagesSuspended(packageNames, suspended, appExtras, launcherExtras, dialogInfo);
+    }
+
+    @Override
+    public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
+            PersistableBundle appExtras, PersistableBundle launcherExtras,
+            SuspendDialogInfo dialogInfo) {
         try {
             return mPM.setPackagesSuspendedAsUser(packageNames, suspended, appExtras,
-                    launcherExtras, dialogMessage, mContext.getOpPackageName(),
+                    launcherExtras, dialogInfo, mContext.getOpPackageName(),
                     getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b57a7d9..4f41da6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -20,6 +20,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -37,6 +38,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -7759,8 +7761,17 @@
      * @see Notification.Builder#setColorized(boolean)
      */
     public static class MediaStyle extends Style {
+        // Changing max media buttons requires also changing templates
+        // (notification_template_material_media and notification_template_material_big_media).
         static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3;
         static final int MAX_MEDIA_BUTTONS = 5;
+        @IdRes private static final int[] MEDIA_BUTTON_IDS = {
+                R.id.action0,
+                R.id.action1,
+                R.id.action2,
+                R.id.action3,
+                R.id.action4,
+        };
 
         private int[] mActionsToShowInCompact = null;
         private MediaSession.Token mToken;
@@ -7874,15 +7885,16 @@
             return false;
         }
 
-        private RemoteViews generateMediaActionButton(Action action, int color) {
+        private void bindMediaActionButton(RemoteViews container, @IdRes int buttonId,
+                Action action, int color) {
             final boolean tombstone = (action.actionIntent == null);
-            RemoteViews button = new BuilderRemoteViews(mBuilder.mContext.getApplicationInfo(),
-                    R.layout.notification_material_media_action);
-            button.setImageViewIcon(R.id.action0, action.getIcon());
+            container.setViewVisibility(buttonId, View.VISIBLE);
+            container.setImageViewIcon(buttonId, action.getIcon());
 
             // If the action buttons should not be tinted, then just use the default
             // notification color. Otherwise, just use the passed-in color.
-            Configuration currentConfig = mBuilder.mContext.getResources().getConfiguration();
+            Resources resources = mBuilder.mContext.getResources();
+            Configuration currentConfig = resources.getConfiguration();
             boolean inNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
                     == Configuration.UI_MODE_NIGHT_YES;
             int tintColor = mBuilder.shouldTintActionButtons() || mBuilder.isColorized()
@@ -7890,13 +7902,21 @@
                     : ContrastColorUtil.resolveColor(mBuilder.mContext,
                             Notification.COLOR_DEFAULT, inNightMode);
 
-            button.setDrawableTint(R.id.action0, false, tintColor,
+            container.setDrawableTint(buttonId, false, tintColor,
                     PorterDuff.Mode.SRC_ATOP);
+
+            final TypedArray typedArray = mBuilder.mContext.obtainStyledAttributes(
+                    new int[]{ android.R.attr.colorControlHighlight });
+            int rippleAlpha = Color.alpha(typedArray.getColor(0, 0));
+            typedArray.recycle();
+            int rippleColor = Color.argb(rippleAlpha, Color.red(tintColor), Color.green(tintColor),
+                    Color.blue(tintColor));
+            container.setRippleDrawableColor(buttonId, ColorStateList.valueOf(rippleColor));
+
             if (!tombstone) {
-                button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
+                container.setOnClickPendingIntent(buttonId, action.actionIntent);
             }
-            button.setContentDescription(R.id.action0, action.title);
-            return button;
+            container.setContentDescription(buttonId, action.title);
         }
 
         private RemoteViews makeMediaContentView() {
@@ -7905,21 +7925,20 @@
                     null /* result */);
 
             final int numActions = mBuilder.mActions.size();
-            final int N = mActionsToShowInCompact == null
+            final int numActionsToShow = mActionsToShowInCompact == null
                     ? 0
                     : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
-            view.removeAllViews(com.android.internal.R.id.media_actions);
-            if (N > 0) {
-                for (int i = 0; i < N; i++) {
-                    if (i >= numActions) {
-                        throw new IllegalArgumentException(String.format(
-                                "setShowActionsInCompactView: action %d out of bounds (max %d)",
-                                i, numActions - 1));
-                    }
-
+            if (numActionsToShow > numActions) {
+                throw new IllegalArgumentException(String.format(
+                        "setShowActionsInCompactView: action %d out of bounds (max %d)",
+                        numActions, numActions - 1));
+            }
+            for (int i = 0; i < MAX_MEDIA_BUTTONS_IN_COMPACT; i++) {
+                if (i < numActionsToShow) {
                     final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
-                    final RemoteViews button = generateMediaActionButton(action, getActionColor());
-                    view.addView(com.android.internal.R.id.media_actions, button);
+                    bindMediaActionButton(view, MEDIA_BUTTON_IDS[i], action, getActionColor());
+                } else {
+                    view.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
                 }
             }
             handleImage(view);
@@ -7949,12 +7968,12 @@
             RemoteViews big = mBuilder.applyStandardTemplate(
                     R.layout.notification_template_material_big_media, false, null /* result */);
 
-            if (actionCount > 0) {
-                big.removeAllViews(com.android.internal.R.id.media_actions);
-                for (int i = 0; i < actionCount; i++) {
-                    final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i),
+            for (int i = 0; i < MAX_MEDIA_BUTTONS; i++) {
+                if (i < actionCount) {
+                    bindMediaActionButton(big, MEDIA_BUTTON_IDS[i], mBuilder.mActions.get(i),
                             getActionColor());
-                    big.addView(com.android.internal.R.id.media_actions, button);
+                } else {
+                    big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
                 }
             }
             handleImage(big);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6c87fe7..0044005 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -377,15 +377,11 @@
                 return new DisplayManager(ctx.getOuterContext());
             }});
 
-        // InputMethodManager has its own cache strategy based on display id to support apps that
-        // still assume InputMethodManager is a per-process singleton and it's safe to directly
-        // access internal fields via reflection.  Hence directly use ServiceFetcher instead of
-        // StaticServiceFetcher/CachedServiceFetcher.
         registerService(Context.INPUT_METHOD_SERVICE, InputMethodManager.class,
-                new ServiceFetcher<InputMethodManager>() {
+                new StaticServiceFetcher<InputMethodManager>() {
             @Override
-            public InputMethodManager getService(ContextImpl ctx) {
-                return InputMethodManager.forContext(ctx);
+            public InputMethodManager createService() {
+                return InputMethodManager.getInstanceInternal();
             }});
 
         registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class,
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index df27d58..c983d4f 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -29,6 +29,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -222,6 +223,18 @@
     }
 
     /**
+     * Provided as a convenience for agent implementations that need an opportunity
+     * to do one-time initialization before the actual backup or restore operation
+     * is begun with information about the calling user.
+     * <p>
+     *
+     * @hide
+     */
+    public void onCreate(UserHandle user) {
+        onCreate();
+    }
+
+    /**
      * Provided as a convenience for agent implementations that need to do some
      * sort of shutdown process after backup or restore is completed.
      * <p>
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 30d5fbc..0aa0535 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -107,20 +107,6 @@
             "android.bluetooth.device.action.FOUND";
 
     /**
-     * Broadcast Action: Remote device disappeared.
-     * <p>Sent when a remote device that was found in the last discovery is not
-     * found in the current discovery.
-     * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
-     *
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    @UnsupportedAppUsage
-    public static final String ACTION_DISAPPEARED =
-            "android.bluetooth.device.action.DISAPPEARED";
-
-    /**
      * Broadcast Action: Bluetooth class of a remote device has changed.
      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
      * #EXTRA_CLASS}.
@@ -654,7 +640,7 @@
     public static final int ACCESS_REJECTED = 2;
 
     /**
-     * No preferrence of physical transport for GATT connections to remote dual-mode devices
+     * No preference of physical transport for GATT connections to remote dual-mode devices
      */
     public static final int TRANSPORT_AUTO = 0;
 
@@ -1971,9 +1957,7 @@
      * <p>The remote device will be authenticated and communication on this socket will be
      * encrypted.
      * <p> Use this socket if an authenticated socket link is possible. Authentication refers
-     * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a
-     * secure socket connection is not possible, use {@link createInsecureLeL2capCocSocket(int,
-     * int)}.
+     * to the authentication of the link key to prevent man-in-the-middle type of attacks.
      *
      * @param psm dynamic PSM value from remote device
      * @return a CoC #BluetoothSocket ready for an outgoing connection
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 29d5a1c..9b7c173 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1292,7 +1292,7 @@
      * <p>After all characteristics have been queued up and verified,
      * {@link #executeReliableWrite} will execute all writes. If a characteristic
      * was not written correctly, calling {@link #abortReliableWrite} will
-     * cancel the current transaction without commiting any values on the
+     * cancel the current transaction without committing any values on the
      * remote device.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index ef1b0bd..13b1b4f 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -522,7 +522,7 @@
      * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
      * invoked when the connection state changes as a result of this function.
      *
-     * <p>The autoConnect paramter determines whether to actively connect to
+     * <p>The autoConnect parameter determines whether to actively connect to
      * the remote device, or rather passively scan and finalize the connection
      * when the remote device is in range/available. Generally, the first ever
      * connection to a device should be direct (autoConnect set to false) and
@@ -695,7 +695,7 @@
     /**
      * Add a service to the list of services to be hosted.
      *
-     * <p>Once a service has been addded to the the list, the service and its
+     * <p>Once a service has been addded to the list, the service and its
      * included characteristics will be provided by the local device.
      *
      * <p>If the local device has already exposed services when this function
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 758c68d..4e88625 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -203,8 +203,8 @@
     /**
      * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
      * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
-     * {@link BluetoothAdapter.listenUsingL2capChannel()} or {@link
-     * BluetoothAdapter.listenUsingInsecureL2capChannel()}. The returned value is undefined if this
+     * {@link BluetoothAdapter#listenUsingL2capChannel()} or {@link
+     * BluetoothAdapter#listenUsingInsecureL2capChannel()}. The returned value is undefined if this
      * method is called on non-L2CAP server sockets.
      *
      * @return the assigned PSM or LE_PSM value depending on transport
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index 58a3696..51324fd 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -56,7 +56,7 @@
     /**
      * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet}
      * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet
-     * contains the started set and it is advertising. If error occured, advertisingSet is
+     * contains the started set and it is advertising. If error occurred, advertisingSet is
      * null, and status will be set to proper error code.
      *
      * @param advertisingSet The advertising set that was started or null if error.
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index b528e39..a086a30 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -95,7 +95,7 @@
  * the SyncManager will wait until the sync adapter is not in use before requesting that
  * it sync an account's data.
  * <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager
- * to intialize the isSyncable state to 1 for that sync adapter for each account that is added.
+ * to initialize the isSyncable state to 1 for that sync adapter for each account that is added.
  * <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it
  * specifies an Intent action of an activity that can be used to adjust the sync adapter's
  * sync settings. The activity must live in the same package as the sync adapter.
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 089cf10..ed3d455 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -224,7 +224,7 @@
          * Create an Item consisting of a single block of (possibly styled) text,
          * with an alternative HTML formatted representation.  You <em>must</em>
          * supply a plain text representation in addition to HTML text; coercion
-         * will not be done from HTML formated text into plain text.
+         * will not be done from HTML formatted text into plain text.
          */
         public Item(CharSequence text, String htmlText) {
             mText = text;
@@ -268,7 +268,7 @@
          * Create a complex Item, containing multiple representations of
          * text, HTML text, Intent, and/or URI.  If providing HTML text, you
          * <em>must</em> supply a plain text representation as well; coercion
-         * will not be done from HTML formated text into plain text.
+         * will not be done from HTML formatted text into plain text.
          */
         public Item(CharSequence text, String htmlText, Intent intent, Uri uri) {
             if (htmlText != null && text == null) {
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 7dc4577..6a3fa6b2 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -637,7 +637,7 @@
 
         /**
          * The selection and arguments to use. An occurrence of '?' in the selection will be
-         * replaced with the corresponding occurence of the selection argument. Any of the
+         * replaced with the corresponding occurrence of the selection argument. Any of the
          * selection arguments may be overwritten by a selection argument back reference as
          * specified by {@link #withSelectionBackReference}.
          * This can only be used with builders of type update, delete, or assert.
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index a882434..c19909d 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1877,7 +1877,7 @@
      * that services the content at uri, starting the provider if necessary. Returns
      * null if there is no provider associated wih the uri. The caller must indicate that they are
      * done with the provider by calling {@link ContentProviderClient#release} which will allow
-     * the system to release the provider it it determines that there is no other reason for
+     * the system to release the provider if it determines that there is no other reason for
      * keeping it active.
      * @param uri specifies which provider should be acquired
      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
@@ -1897,7 +1897,7 @@
      * with the authority of name, starting the provider if necessary. Returns
      * null if there is no provider associated wih the uri. The caller must indicate that they are
      * done with the provider by calling {@link ContentProviderClient#release} which will allow
-     * the system to release the provider it it determines that there is no other reason for
+     * the system to release the provider if it determines that there is no other reason for
      * keeping it active.
      * @param name specifies which provider should be acquired
      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d711574..db4adcf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -187,7 +187,7 @@
      *
      * <p>This was the legacy (but undocumented) behavior in and
      * before Gingerbread (Android 2.3) and this flag is implied when
-     * targetting such releases.  For applications targetting SDK
+     * targeting such releases.  For applications targeting SDK
      * versions <em>greater than</em> Android 2.3, this flag must be
      * explicitly set if desired.
      *
@@ -2840,7 +2840,7 @@
      *
      * @param service Description of the service to be stopped.  The Intent must be either
      *      fully explicit (supplying a component name) or specify a specific package
-     *      name it is targetted to.
+     *      name it is targeted to.
      *
      * @return If there is a service matching the given Intent that is already
      * running, then it is stopped and {@code true} is returned; else {@code false} is returned.
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 4e46d571..4ccafab 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -36,7 +36,7 @@
  * perform, either through the
  * {@link #CursorLoader(Context, Uri, String[], String, String[], String)} or
  * creating an empty instance with {@link #CursorLoader(Context)} and filling
- * in the desired paramters with {@link #setUri(Uri)}, {@link #setSelection(String)},
+ * in the desired parameters with {@link #setUri(Uri)}, {@link #setSelection(String)},
  * {@link #setSelectionArgs(String[])}, {@link #setSortOrder(String)},
  * and {@link #setProjection(String[])}.
  *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index af910e0..8913748 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3955,6 +3955,12 @@
     public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
 
     /**
+     * An parcelable extra used with {@link #ACTION_SERVICE_STATE} representing the service state.
+     * @hide
+     */
+    public static final String EXTRA_SERVICE_STATE = "android.intent.extra.SERVICE_STATE";
+
+    /**
      * The name of the extra used to define the text to be processed, as a
      * CharSequence. Note that this may be a styled CharSequence, so you must use
      * {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
@@ -5523,7 +5529,7 @@
     /**
      * If set and this intent is being used to launch a new activity from an
      * existing one, then the reply target of the existing activity will be
-     * transfered to the new activity.  This way the new activity can call
+     * transferred to the new activity.  This way, the new activity can call
      * {@link android.app.Activity#setResult} and have that result sent back to
      * the reply target of the original activity.
      */
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 0469a90..36d8a37 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -479,7 +479,7 @@
     /**
      * Modify priority of this filter.  This only affects receiver filters.
      * The priority of activity filters are set in XML and cannot be changed
-     * programatically. The default priority is 0. Positive values will be
+     * programmatically. The default priority is 0. Positive values will be
      * before the default, lower values will be after it. Applications should
      * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
      * smaller than {@link #SYSTEM_HIGH_PRIORITY} .
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 5926af6..0a4f4eb 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1408,5 +1408,13 @@
          * @attr ref android.R.styleable#AndroidManifestLayout_minHeight
          */
         public final int minHeight;
+
+        /**
+         * Returns if this {@link WindowLayout} has specified bounds.
+         * @hide
+         */
+        public boolean hasSpecifiedSize() {
+            return width >= 0 || height >= 0 || widthFraction >= 0 || heightFraction >= 0;
+        }
     }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 225b6cf..c33f143 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -236,7 +236,7 @@
     
     /**
      * Value for {@link #flags}: true when the application knows how to
-     * accomodate different screen densities.  Corresponds to
+     * accommodate different screen densities.  Corresponds to
      * {@link android.R.styleable#AndroidManifestSupportsScreens_anyDensity
      * android:anyDensity}.
      */
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 6a20c93..4a4de51 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -43,6 +43,7 @@
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VersionedPackage;
@@ -273,7 +274,7 @@
 
     String[] setPackagesSuspendedAsUser(in String[] packageNames, boolean suspended,
             in PersistableBundle appExtras, in PersistableBundle launcherExtras,
-            String dialogMessage, String callingPackage, int userId);
+            in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
 
     boolean isPackageSuspendedForUser(String packageName, int userId);
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3032d16..dfb8128 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5187,6 +5187,7 @@
      * @param packageName The name of the package to query
      * @throws IllegalArgumentException if the given package name is not installed
      */
+    @Nullable
     public abstract String getInstallerPackageName(String packageName);
 
     /**
@@ -5663,7 +5664,7 @@
      * {@link Manifest.permission#MANAGE_USERS} to use this api.</p>
      *
      * @param packageNames The names of the packages to set the suspended status.
-     * @param suspended If set to {@code true} than the packages will be suspended, if set to
+     * @param suspended If set to {@code true}, the packages will be suspended, if set to
      * {@code false}, the packages will be unsuspended.
      * @param appExtras An optional {@link PersistableBundle} that the suspending app can provide
      *                  which will be shared with the apps being suspended. Ignored if
@@ -5675,15 +5676,76 @@
      *                      suspended app.
      *
      * @return an array of package names for which the suspended status could not be set as
-     * requested in this method.
+     * requested in this method. Returns {@code null} if {@code packageNames} was {@code null}.
+     *
+     * @deprecated use {@link #setPackagesSuspended(String[], boolean, PersistableBundle,
+     * PersistableBundle, android.content.pm.SuspendDialogInfo)} instead.
+     *
+     * @hide
+     */
+    @SystemApi
+    @Deprecated
+    @RequiresPermission(Manifest.permission.SUSPEND_APPS)
+    @Nullable
+    public String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended,
+            @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras,
+            @Nullable String dialogMessage) {
+        throw new UnsupportedOperationException("setPackagesSuspended not implemented");
+    }
+
+    /**
+     * Puts the given packages in a suspended state, where attempts at starting activities are
+     * denied.
+     *
+     * <p>The suspended application's notifications and all of its windows will be hidden, any
+     * of its started activities will be stopped and it won't be able to ring the device.
+     * It doesn't remove the data or the actual package file.
+     *
+     * <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
+     * {@link Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} intent if the suspending app declares an
+     * activity which handles this action.
+     *
+     * <p>The packages being suspended must already be installed. If a package is uninstalled, it
+     * will no longer be suspended.
+     *
+     * <p>Optionally, the suspending app can provide extra information in the form of
+     * {@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.
+     *
+     * @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
+     * {@code false}, the packages will be unsuspended.
+     * @param appExtras An optional {@link PersistableBundle} that the suspending app can provide
+     *                  which will be shared with the apps being suspended. Ignored if
+     *                  {@code suspended} is false.
+     * @param launcherExtras An optional {@link PersistableBundle} that the suspending app can
+     *                       provide which will be shared with the launcher. Ignored if
+     *                       {@code suspended} is false.
+     * @param dialogInfo An optional {@link SuspendDialogInfo} object describing the dialog that
+     *                   should be shown to the user when they try to launch a suspended app.
+     *                   Ignored if {@code suspended} is false.
+     *
+     * @return an array of package names for which the suspended status could not be set as
+     * requested in this method. Returns {@code null} if {@code packageNames} was {@code null}.
+     *
+     * @see #isPackageSuspended
+     * @see SuspendDialogInfo
+     * @see SuspendDialogInfo.Builder
+     * @see Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS
      *
      * @hide
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.SUSPEND_APPS)
-    public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
+    @Nullable
+    public String[] setPackagesSuspended(@Nullable String[] packageNames, boolean suspended,
             @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras,
-            String dialogMessage) {
+            @Nullable SuspendDialogInfo dialogInfo) {
         throw new UnsupportedOperationException("setPackagesSuspended not implemented");
     }
 
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index b5b4432..4f58321 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager.ApplicationInfoFlags;
@@ -205,6 +206,29 @@
             @PackageInfoFlags int flags, int filterCallingUid, int userId);
 
     /**
+     * Return a List of all application packages that are installed on the
+     * device, for a specific user. If flag GET_UNINSTALLED_PACKAGES has been
+     * set, a list of all applications including those deleted with
+     * {@code DONT_DELETE_DATA} (partially installed apps with data directory)
+     * will be returned.
+     *
+     * @param flags Additional option flags to modify the data returned.
+     * @param userId The user for whom the installed applications are to be
+     *            listed
+     * @param callingUid The uid of the original caller app
+     * @return A List of ApplicationInfo objects, one for each installed
+     *         application. In the unlikely case there are no installed
+     *         packages, an empty list is returned. If flag
+     *         {@code MATCH_UNINSTALLED_PACKAGES} is set, the application
+     *         information is retrieved from the list of uninstalled
+     *         applications (which includes installed applications as well as
+     *         applications with data directory i.e. applications which had been
+     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     */
+    public abstract List<ApplicationInfo> getInstalledApplications(
+            @ApplicationInfoFlags int flags, @UserIdInt int userId, int callingUid);
+
+    /**
      * Retrieve launcher extras for a suspended package provided to the system in
      * {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
      * PersistableBundle, String)}.
@@ -243,14 +267,15 @@
     public abstract String getSuspendingPackage(String suspendedPackage, int userId);
 
     /**
-     * Get the dialog message to be shown to the user when they try to launch a suspended
-     * application.
+     * Get the information describing the dialog to be shown to the user when they try to launch a
+     * suspended application.
      *
      * @param suspendedPackage The package that has been suspended.
      * @param userId The user for which to check.
-     * @return The dialog message to be shown to the user.
+     * @return A {@link SuspendDialogInfo} object describing the dialog to be shown.
      */
-    public abstract String getSuspendedDialogMessage(String suspendedPackage, int userId);
+    @Nullable
+    public abstract SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId);
 
     /**
      * Do a straight uid lookup for the given package/application in the given user.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 24675d3..046e9e7 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -47,6 +47,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityTaskManager;
+import android.app.AppDetailsActivity;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -2440,17 +2441,17 @@
         }
 
 
-        final int NS = PermissionManager.SPLIT_PERMISSIONS.length;
+        final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
         for (int is=0; is<NS; is++) {
             final PermissionManager.SplitPermissionInfo spi =
-                    PermissionManager.SPLIT_PERMISSIONS[is];
+                    PermissionManager.SPLIT_PERMISSIONS.get(is);
             if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
-                    || !pkg.requestedPermissions.contains(spi.getRootPermission())) {
+                    || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
                 continue;
             }
-            final String[] newPerms = spi.getNewPermissions();
-            for (int in = 0; in < newPerms.length; in++) {
-                final String perm = newPerms[in];
+            final List<String> newPerms = spi.getNewPermissions();
+            for (int in = 0; in < newPerms.size(); in++) {
+                final String perm = newPerms.get(in);
                 if (!pkg.requestedPermissions.contains(perm)) {
                     pkg.requestedPermissions.add(perm);
                 }
@@ -3882,6 +3883,11 @@
             }
         }
 
+        // Add a hidden app detail activity which forwards user to App Details page.
+        Activity a = generateAppDetailsHiddenActivity(owner, flags, outError,
+                owner.baseHardwareAccelerated);
+        owner.activities.add(a);
+
         if (hasActivityOrder) {
             Collections.sort(owner.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
         }
@@ -4121,9 +4127,14 @@
                 return false;
             }
         } else {
-            outInfo.name
+            String outInfoName
                 = buildClassName(owner.applicationInfo.packageName, name, outError);
-            if (outInfo.name == null) {
+            if (AppDetailsActivity.class.getName().equals(outInfoName)) {
+                outError[0] = tag + " invalid android:name";
+                return false;
+            }
+            outInfo.name = outInfoName;
+            if (outInfoName == null) {
                 return false;
             }
         }
@@ -4162,6 +4173,45 @@
         return true;
     }
 
+    /**
+     * Generate activity object that forwards user to App Details page automatically.
+     * This activity should be invisible to user and user should not know or see it.
+     */
+    private @NonNull PackageParser.Activity generateAppDetailsHiddenActivity(
+            PackageParser.Package owner, int flags, String[] outError,
+            boolean hardwareAccelerated) {
+
+        // Build custom App Details activity info instead of parsing it from xml
+        Activity a = new Activity(owner, AppDetailsActivity.class.getName(), new ActivityInfo());
+        a.owner = owner;
+        a.setPackageName(owner.packageName);
+
+        a.info.theme = 0;
+        a.info.exported = true;
+        a.info.name = AppDetailsActivity.class.getName();
+        a.info.processName = owner.applicationInfo.processName;
+        a.info.uiOptions = a.info.applicationInfo.uiOptions;
+        a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
+                ":app_details", outError);
+        a.info.enabled = true;
+        a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+        a.info.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
+        a.info.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
+        a.info.configChanges = getActivityConfigChanges(0, 0);
+        a.info.softInputMode = 0;
+        a.info.persistableMode = ActivityInfo.PERSIST_NEVER;
+        a.info.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+        a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+        a.info.lockTaskLaunchMode = 0;
+        a.info.encryptionAware = a.info.directBootAware = false;
+        a.info.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
+        a.info.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
+        if (hardwareAccelerated) {
+            a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
+        }
+        return a;
+    }
+
     private Activity parseActivity(Package owner, Resources res,
             XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
             boolean receiver, boolean hardwareAccelerated)
@@ -7132,10 +7182,16 @@
         ComponentName componentName;
         String componentShortName;
 
-        public Component(Package _owner) {
-            owner = _owner;
-            intents = null;
-            className = null;
+        public Component(Package owner, ArrayList<II> intents, String className) {
+            this.owner = owner;
+            this.intents = intents;
+            this.className = className;
+        }
+
+        public Component(Package owner) {
+            this.owner = owner;
+            this.intents = null;
+            this.className = null;
         }
 
         public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
@@ -7600,6 +7656,13 @@
             return mHasMaxAspectRatio;
         }
 
+        // To construct custom activity which does not exist in manifest
+        Activity(final Package owner, final String className, final ActivityInfo info) {
+            super(owner, new ArrayList<>(0), className);
+            this.info = info;
+            this.info.applicationInfo = owner.applicationInfo;
+        }
+
         public Activity(final ParseComponentArgs args, final ActivityInfo _info) {
             super(args, _info);
             info = _info;
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 248d523..e21c33a 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -33,6 +33,7 @@
 import android.os.PersistableBundle;
 import android.util.ArraySet;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
 import java.util.Arrays;
@@ -50,7 +51,7 @@
     public boolean hidden; // Is the app restricted by owner / admin
     public boolean suspended;
     public String suspendingPackage;
-    public String dialogMessage; // Message to show when a suspended package launch attempt is made
+    public SuspendDialogInfo dialogInfo;
     public PersistableBundle suspendedAppExtras;
     public PersistableBundle suspendedLauncherExtras;
     public boolean instantApp;
@@ -79,6 +80,7 @@
         installReason = PackageManager.INSTALL_REASON_UNKNOWN;
     }
 
+    @VisibleForTesting
     public PackageUserState(PackageUserState o) {
         ceDataInode = o.ceDataInode;
         installed = o.installed;
@@ -87,7 +89,7 @@
         hidden = o.hidden;
         suspended = o.suspended;
         suspendingPackage = o.suspendingPackage;
-        dialogMessage = o.dialogMessage;
+        dialogInfo = o.dialogInfo;
         suspendedAppExtras = o.suspendedAppExtras;
         suspendedLauncherExtras = o.suspendedLauncherExtras;
         instantApp = o.instantApp;
@@ -217,7 +219,7 @@
                     || !suspendingPackage.equals(oldState.suspendingPackage)) {
                 return false;
             }
-            if (!Objects.equals(dialogMessage, oldState.dialogMessage)) {
+            if (!Objects.equals(dialogInfo, oldState.dialogInfo)) {
                 return false;
             }
             if (!BaseBundle.kindofEquals(suspendedAppExtras,
diff --git a/proto/src/stats_enums.proto b/core/java/android/content/pm/SuspendDialogInfo.aidl
similarity index 76%
copy from proto/src/stats_enums.proto
copy to core/java/android/content/pm/SuspendDialogInfo.aidl
index 6c892cf..5e711cf 100644
--- a/proto/src/stats_enums.proto
+++ b/core/java/android/content/pm/SuspendDialogInfo.aidl
@@ -13,14 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.content.pm;
 
-syntax = "proto2";
-
-package android.os.statsd;
-option java_package = "com.android.os";
-option java_outer_classname = "StatsEnums";
-
-enum EventType {
-  // Unknown.
-  TYPE_UNKNOWN = 0;
-}
+parcelable SuspendDialogInfo;
diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java
new file mode 100644
index 0000000..c798c99
--- /dev/null
+++ b/core/java/android/content/pm/SuspendDialogInfo.java
@@ -0,0 +1,379 @@
+/*
+ * 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.content.pm;
+
+import static android.content.res.ResourceId.ID_NULL;
+
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.SystemApi;
+import android.content.res.ResourceId;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.util.Slog;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * A container to describe the dialog to be shown when the user tries to launch a suspended
+ * application.
+ * The suspending app can customize the dialog's following attributes:
+ * <ul>
+ * <li>The dialog icon, by providing a resource id.
+ * <li>The title text, by providing a resource id.
+ * <li>The text of the dialog's body, by providing a resource id or a string.
+ * <li>The text on the neutral button which starts the
+ * {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS SHOW_SUSPENDED_APP_DETAILS}
+ * activity, by providing a resource id.
+ * </ul>
+ * System defaults are used whenever any of these are not provided, or any of the provided resource
+ * ids cannot be resolved at the time of displaying the dialog.
+ *
+ * @hide
+ * @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+ * SuspendDialogInfo)
+ * @see Builder
+ */
+@SystemApi
+public final class SuspendDialogInfo implements Parcelable {
+    private static final String TAG = SuspendDialogInfo.class.getSimpleName();
+    private static final String XML_ATTR_ICON_RES_ID = "iconResId";
+    private static final String XML_ATTR_TITLE_RES_ID = "titleResId";
+    private static final String XML_ATTR_DIALOG_MESSAGE_RES_ID = "dialogMessageResId";
+    private static final String XML_ATTR_DIALOG_MESSAGE = "dialogMessage";
+    private static final String XML_ATTR_BUTTON_TEXT_RES_ID = "buttonTextResId";
+
+    private final int mIconResId;
+    private final int mTitleResId;
+    private final int mDialogMessageResId;
+    private final String mDialogMessage;
+    private final int mNeutralButtonTextResId;
+
+    /**
+     * @return the resource id of the icon to be used with the dialog
+     * @hide
+     */
+    @DrawableRes
+    public int getIconResId() {
+        return mIconResId;
+    }
+
+    /**
+     * @return the resource id of the title to be used with the dialog
+     * @hide
+     */
+    @StringRes
+    public int getTitleResId() {
+        return mTitleResId;
+    }
+
+    /**
+     * @return the resource id of the text to be shown in the dialog's body
+     * @hide
+     */
+    @StringRes
+    public int getDialogMessageResId() {
+        return mDialogMessageResId;
+    }
+
+    /**
+     * @return the text to be shown in the dialog's body. Returns {@code null} if
+     * {@link #getDialogMessageResId()} returns a valid resource id.
+     * @hide
+     */
+    @Nullable
+    public String getDialogMessage() {
+        return mDialogMessage;
+    }
+
+    /**
+     * @return the text to be shown
+     * @hide
+     */
+    @StringRes
+    public int getNeutralButtonTextResId() {
+        return mNeutralButtonTextResId;
+    }
+
+    /**
+     * @hide
+     */
+    public void saveToXml(XmlSerializer out) throws IOException {
+        if (mIconResId != ID_NULL) {
+            XmlUtils.writeIntAttribute(out, XML_ATTR_ICON_RES_ID, mIconResId);
+        }
+        if (mTitleResId != ID_NULL) {
+            XmlUtils.writeIntAttribute(out, XML_ATTR_TITLE_RES_ID, mTitleResId);
+        }
+        if (mDialogMessageResId != ID_NULL) {
+            XmlUtils.writeIntAttribute(out, XML_ATTR_DIALOG_MESSAGE_RES_ID, mDialogMessageResId);
+        } else {
+            XmlUtils.writeStringAttribute(out, XML_ATTR_DIALOG_MESSAGE, mDialogMessage);
+        }
+        if (mNeutralButtonTextResId != ID_NULL) {
+            XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_TEXT_RES_ID, mNeutralButtonTextResId);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static SuspendDialogInfo restoreFromXml(XmlPullParser in) {
+        final SuspendDialogInfo.Builder dialogInfoBuilder = new SuspendDialogInfo.Builder();
+        try {
+            final int iconId = XmlUtils.readIntAttribute(in, XML_ATTR_ICON_RES_ID, ID_NULL);
+            final int titleId = XmlUtils.readIntAttribute(in, XML_ATTR_TITLE_RES_ID, ID_NULL);
+            final int buttonTextId = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_TEXT_RES_ID,
+                    ID_NULL);
+            final int dialogMessageResId = XmlUtils.readIntAttribute(
+                    in, XML_ATTR_DIALOG_MESSAGE_RES_ID, ID_NULL);
+            final String dialogMessage = XmlUtils.readStringAttribute(in, XML_ATTR_DIALOG_MESSAGE);
+
+            if (iconId != ID_NULL) {
+                dialogInfoBuilder.setIcon(iconId);
+            }
+            if (titleId != ID_NULL) {
+                dialogInfoBuilder.setTitle(titleId);
+            }
+            if (buttonTextId != ID_NULL) {
+                dialogInfoBuilder.setNeutralButtonText(buttonTextId);
+            }
+            if (dialogMessageResId != ID_NULL) {
+                dialogInfoBuilder.setMessage(dialogMessageResId);
+            } else if (dialogMessage != null) {
+                dialogInfoBuilder.setMessage(dialogMessage);
+            }
+        } catch (Exception e) {
+            Slog.e(TAG, "Exception while parsing from xml. Some fields may default", e);
+        }
+        return dialogInfoBuilder.build();
+    }
+
+    @Override
+    public int hashCode() {
+        int hashCode = mIconResId;
+        hashCode = 31 * hashCode + mTitleResId;
+        hashCode = 31 * hashCode + mNeutralButtonTextResId;
+        hashCode = 31 * hashCode + mDialogMessageResId;
+        hashCode = 31 * hashCode + Objects.hashCode(mDialogMessage);
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof SuspendDialogInfo)) {
+            return false;
+        }
+        final SuspendDialogInfo otherDialogInfo = (SuspendDialogInfo) obj;
+        return mIconResId == otherDialogInfo.mIconResId
+                && mTitleResId == otherDialogInfo.mTitleResId
+                && mDialogMessageResId == otherDialogInfo.mDialogMessageResId
+                && mNeutralButtonTextResId == otherDialogInfo.mNeutralButtonTextResId
+                && Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder("SuspendDialogInfo: {");
+        if (mIconResId != ID_NULL) {
+            builder.append("mIconId = 0x");
+            builder.append(Integer.toHexString(mIconResId));
+            builder.append(" ");
+        }
+        if (mTitleResId != ID_NULL) {
+            builder.append("mTitleResId = 0x");
+            builder.append(Integer.toHexString(mTitleResId));
+            builder.append(" ");
+        }
+        if (mNeutralButtonTextResId != ID_NULL) {
+            builder.append("mNeutralButtonTextResId = 0x");
+            builder.append(Integer.toHexString(mNeutralButtonTextResId));
+            builder.append(" ");
+        }
+        if (mDialogMessageResId != ID_NULL) {
+            builder.append("mDialogMessageResId = 0x");
+            builder.append(Integer.toHexString(mDialogMessageResId));
+            builder.append(" ");
+        } else if (mDialogMessage != null) {
+            builder.append("mDialogMessage = \"");
+            builder.append(mDialogMessage);
+            builder.append("\" ");
+        }
+        builder.append("}");
+        return builder.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        dest.writeInt(mIconResId);
+        dest.writeInt(mTitleResId);
+        dest.writeInt(mDialogMessageResId);
+        dest.writeString(mDialogMessage);
+        dest.writeInt(mNeutralButtonTextResId);
+    }
+
+    private SuspendDialogInfo(Parcel source) {
+        mIconResId = source.readInt();
+        mTitleResId = source.readInt();
+        mDialogMessageResId = source.readInt();
+        mDialogMessage = source.readString();
+        mNeutralButtonTextResId = source.readInt();
+    }
+
+    SuspendDialogInfo(Builder b) {
+        mIconResId = b.mIconResId;
+        mTitleResId = b.mTitleResId;
+        mDialogMessageResId = b.mDialogMessageResId;
+        mDialogMessage = (mDialogMessageResId == ID_NULL) ? b.mDialogMessage : null;
+        mNeutralButtonTextResId = b.mNeutralButtonTextResId;
+    }
+
+    public static final Creator<SuspendDialogInfo> CREATOR = new Creator<SuspendDialogInfo>() {
+        @Override
+        public SuspendDialogInfo createFromParcel(Parcel source) {
+            return new SuspendDialogInfo(source);
+        }
+
+        @Override
+        public SuspendDialogInfo[] newArray(int size) {
+            return new SuspendDialogInfo[size];
+        }
+    };
+
+    /**
+     * Builder to build a {@link SuspendDialogInfo} object.
+     */
+    public static final class Builder {
+        private int mDialogMessageResId = ID_NULL;
+        private String mDialogMessage;
+        private int mTitleResId = ID_NULL;
+        private int mIconResId = ID_NULL;
+        private int mNeutralButtonTextResId = ID_NULL;
+
+        /**
+         * Set the resource id of the icon to be used. If not provided, no icon will be shown.
+         *
+         * @param resId The resource id of the icon.
+         * @return this builder object.
+         */
+        @NonNull
+        public Builder setIcon(@DrawableRes int resId) {
+            Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided");
+            mIconResId = resId;
+            return this;
+        }
+
+        /**
+         * Set the resource id of the title text to be displayed. If this is not provided, the
+         * system will use a default title.
+         *
+         * @param resId The resource id of the title.
+         * @return this builder object.
+         */
+        @NonNull
+        public Builder setTitle(@StringRes int resId) {
+            Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided");
+            mTitleResId = resId;
+            return this;
+        }
+
+        /**
+         * Set the text to show in the body of the dialog. Ignored if a resource id is set via
+         * {@link #setMessage(int)}.
+         * <p>
+         * The system will use {@link String#format(Locale, String, Object...) String.format} to
+         * insert the suspended app name into the message, so an example format string could be
+         * {@code "The app %1$s is currently suspended"}. This is optional - if the string passed in
+         * {@code message} does not accept an argument, it will be used as is.
+         *
+         * @param message The dialog message.
+         * @return this builder object.
+         * @see #setMessage(int)
+         */
+        @NonNull
+        public Builder setMessage(@NonNull String message) {
+            Preconditions.checkStringNotEmpty(message, "Message cannot be null or empty");
+            mDialogMessage = message;
+            return this;
+        }
+
+        /**
+         * Set the resource id of the dialog message to be shown. If no dialog message is provided
+         * via either this method or {@link #setMessage(String)}, the system will use a
+         * default message.
+         * <p>
+         * The system will use {@link android.content.res.Resources#getString(int, Object...)
+         * getString} to insert the suspended app name into the message, so an example format string
+         * could be {@code "The app %1$s is currently suspended"}. This is optional - if the string
+         * referred to by {@code resId} does not accept an argument, it will be used as is.
+         *
+         * @param resId The resource id of the dialog message.
+         * @return this builder object.
+         * @see #setMessage(String)
+         */
+        @NonNull
+        public Builder setMessage(@StringRes int resId) {
+            Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided");
+            mDialogMessageResId = resId;
+            return this;
+        }
+
+        /**
+         * Set the resource id of text to be shown on the neutral button. Tapping this button starts
+         * the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity. If this is
+         * not provided, the system will use a default text.
+         *
+         * @param resId The resource id of the button text
+         * @return this builder object.
+         */
+        @NonNull
+        public Builder setNeutralButtonText(@StringRes int resId) {
+            Preconditions.checkArgument(ResourceId.isValid(resId), "Invalid resource id provided");
+            mNeutralButtonTextResId = resId;
+            return this;
+        }
+
+        /**
+         * Build the final object based on given inputs.
+         *
+         * @return The {@link SuspendDialogInfo} object built using this builder.
+         */
+        @NonNull
+        public SuspendDialogInfo build() {
+            return new SuspendDialogInfo(this);
+        }
+    }
+}
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 8f8f676..42e7ac7 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -53,7 +53,7 @@
     }
 
     /**
-     * Execute this SQL statement, if the the number of rows affected by execution of this SQL
+     * Execute this SQL statement, if the number of rows affected by execution of this SQL
      * statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
      *
      * @return the number of rows affected by this SQL statement execution.
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 486b054..d4dc181 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2090,7 +2090,7 @@
 
     /**
      * <p>Optimized for dim settings where the main light source
-     * is a flame.</p>
+     * is a candle.</p>
      * @see CaptureRequest#CONTROL_SCENE_MODE
      */
     public static final int CONTROL_SCENE_MODE_CANDLELIGHT = 15;
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 917644d..6609b76 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -133,6 +133,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public boolean registerIntent(@NonNull PendingIntent intent, long nanoAppId) {
         // TODO: Implement this
         return false;
@@ -146,6 +147,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public boolean unregisterIntent(@NonNull PendingIntent intent) {
         // TODO: Implement this
         return false;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 36f3586..f94d69b 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -749,6 +749,7 @@
      *
      * @see ContextHubClientCallback
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback,
             @NonNull @CallbackExecutor Executor executor) {
@@ -785,6 +786,7 @@
      *
      * @see ContextHubClientCallback
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
             @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) {
         return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain()));
@@ -811,6 +813,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
             @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
             @NonNull ContextHubClientCallback callback,
@@ -835,6 +838,7 @@
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
             @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
             @NonNull ContextHubClientCallback callback) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8333b81..1fbfa40 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -83,6 +83,7 @@
 @SystemService(Context.CONNECTIVITY_SERVICE)
 public class ConnectivityManager {
     private static final String TAG = "ConnectivityManager";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     /**
      * A change in network connectivity has occurred. A default connection has either
@@ -2493,6 +2494,7 @@
      * {@hide}
      */
     public void reportInetCondition(int networkType, int percentage) {
+        printStackTrace();
         try {
             mService.reportInetCondition(networkType, percentage);
         } catch (RemoteException e) {
@@ -2513,6 +2515,7 @@
      */
     @Deprecated
     public void reportBadNetwork(Network network) {
+        printStackTrace();
         try {
             // One of these will be ignored because it matches system's current state.
             // The other will trigger the necessary reevaluation.
@@ -2535,6 +2538,7 @@
      *                        Internet using {@code network} or {@code false} if not.
      */
     public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
+        printStackTrace();
         try {
             mService.reportNetworkConnectivity(network, hasConnectivity);
         } catch (RemoteException e) {
@@ -2727,8 +2731,11 @@
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
-    @UnsupportedAppUsage
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK})
+    @SystemApi
     public void setAirplaneMode(boolean enable) {
         try {
             mService.setAirplaneMode(enable);
@@ -3073,6 +3080,7 @@
 
     private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
             int timeoutMs, int action, int legacyType, CallbackHandler handler) {
+        printStackTrace();
         checkCallbackNotNull(callback);
         Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
         final NetworkRequest request;
@@ -3332,6 +3340,7 @@
      *         {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
      */
     public void requestNetwork(NetworkRequest request, PendingIntent operation) {
+        printStackTrace();
         checkPendingIntentNotNull(operation);
         try {
             mService.pendingRequestForNetwork(request.networkCapabilities, operation);
@@ -3355,6 +3364,7 @@
      *                  corresponding NetworkRequest you'd like to remove. Cannot be null.
      */
     public void releaseNetworkRequest(PendingIntent operation) {
+        printStackTrace();
         checkPendingIntentNotNull(operation);
         try {
             mService.releasePendingNetworkRequest(operation);
@@ -3439,6 +3449,7 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
+        printStackTrace();
         checkPendingIntentNotNull(operation);
         try {
             mService.pendingListenForNetwork(request.networkCapabilities, operation);
@@ -3520,6 +3531,7 @@
      * @param networkCallback The {@link NetworkCallback} used when making the request.
      */
     public void unregisterNetworkCallback(NetworkCallback networkCallback) {
+        printStackTrace();
         checkCallbackNotNull(networkCallback);
         final List<NetworkRequest> reqs = new ArrayList<>();
         // Find all requests associated to this callback and stop callback triggers immediately.
@@ -3948,4 +3960,19 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    private void printStackTrace() {
+        if (DEBUG) {
+            final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+            final StringBuffer sb = new StringBuffer();
+            for (int i = 3; i < callStack.length; i++) {
+                final String stackTrace = callStack[i].toString();
+                if (stackTrace == null || stackTrace.contains("android.os")) {
+                    break;
+                }
+                sb.append(" [").append(stackTrace).append("]");
+            }
+            Log.d(TAG, "StackLog:" + sb.toString());
+        }
+    }
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 26c2033..412a700 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
@@ -1112,19 +1113,37 @@
         }
 
         /** The name of this partition, e.g. "system", or "vendor" */
+        @NonNull
         public String getName() {
             return mName;
         }
 
         /** The build fingerprint of this partition, see {@link Build#FINGERPRINT}. */
+        @NonNull
         public String getFingerprint() {
             return mFingerprint;
         }
 
         /** The time (ms since epoch), at which this partition was built, see {@link Build#TIME}. */
-        public long getTimeMillis() {
+        public long getBuildTimeMillis() {
             return mTimeMs;
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Partition)) {
+                return false;
+            }
+            Partition op = (Partition) o;
+            return mName.equals(op.mName)
+                    && mFingerprint.equals(op.mFingerprint)
+                    && mTimeMs == op.mTimeMs;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mName, mFingerprint, mTimeMs);
+        }
     }
 
     /**
@@ -1133,7 +1152,8 @@
      * The list includes partitions that are suitable candidates for over-the-air updates. This is
      * not an exhaustive list of partitions on the device.
      */
-    public static List<Partition> getPartitions() {
+    @NonNull
+    public static List<Partition> getFingerprintedPartitions() {
         ArrayList<Partition> partitions = new ArrayList();
 
         String[] names = new String[] {
diff --git a/core/java/android/os/DumpstateOptions.java b/core/java/android/os/DumpstateOptions.java
new file mode 100644
index 0000000..53037b24
--- /dev/null
+++ b/core/java/android/os/DumpstateOptions.java
@@ -0,0 +1,57 @@
+/*
+ * 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.os;
+
+/**
+ * Options passed to dumpstate service.
+ *
+ * @hide
+ */
+public final class DumpstateOptions implements Parcelable {
+    // If true the caller can get callbacks with per-section
+    // progress details.
+    private final boolean mGetSectionDetails;
+    // Name of the caller.
+    private final String mName;
+
+    public DumpstateOptions(Parcel in) {
+        mGetSectionDetails = in.readBoolean();
+        mName = in.readString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+     public void writeToParcel(Parcel out, int flags) {
+        out.writeBoolean(mGetSectionDetails);
+        out.writeString(mName);
+    }
+
+    public static final Parcelable.Creator<DumpstateOptions> CREATOR =
+            new Parcelable.Creator<DumpstateOptions>() {
+        public DumpstateOptions createFromParcel(Parcel in) {
+            return new DumpstateOptions(in);
+        }
+
+        public DumpstateOptions[] newArray(int size) {
+            return new DumpstateOptions[size];
+        }
+    };
+}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index df3aae2..5f65620 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -55,7 +55,7 @@
      * Set up GraphicsEnvironment
      */
     public void setup(Context context, Bundle coreSettings) {
-        setupGpuLayers(context, coreSettings);
+        setupGpuLayers(context);
         setupAngle(context, coreSettings);
         chooseDriver(context);
     }
@@ -81,54 +81,27 @@
     }
 
     /**
-     * Return the debug layer app's on-disk and in-APK lib directories
-     */
-    private static String getDebugLayerAppPaths(Context context, String app) {
-        ApplicationInfo appInfo;
-        try {
-            appInfo = context.getPackageManager().getApplicationInfo(
-                    app, PackageManager.MATCH_ALL);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Debug layer app '" + app + "' not installed");
-
-            return null;
-        }
-
-        String abi = chooseAbi(appInfo);
-
-        StringBuilder sb = new StringBuilder();
-        sb.append(appInfo.nativeLibraryDir)
-            .append(File.pathSeparator);
-        sb.append(appInfo.sourceDir)
-            .append("!/lib/")
-            .append(abi);
-        String paths = sb.toString();
-
-        if (DEBUG) Log.v(TAG, "Debug layer app libs: " + paths);
-
-        return paths;
-    }
-
-    /**
      * Set up layer search paths for all apps
      * If debuggable, check for additional debug settings
      */
-    private void setupGpuLayers(Context context, Bundle coreSettings) {
+    private void setupGpuLayers(Context context) {
 
         String layerPaths = "";
 
         // Only enable additional debug functionality if the following conditions are met:
-        // 1. App is debuggable or device is rooted
+        // 1. App is debuggable
         // 2. ENABLE_GPU_DEBUG_LAYERS is true
         // 3. Package name is equal to GPU_DEBUG_APP
 
-        if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
+        if (isDebuggable(context)) {
 
-            int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);
+            int enable = Settings.Global.getInt(context.getContentResolver(),
+                                                Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);
 
             if (enable != 0) {
 
-                String gpuDebugApp = coreSettings.getString(Settings.Global.GPU_DEBUG_APP);
+                String gpuDebugApp = Settings.Global.getString(context.getContentResolver(),
+                                                               Settings.Global.GPU_DEBUG_APP);
 
                 String packageName = context.getPackageName();
 
@@ -142,22 +115,8 @@
                     // the layers specified by the app.
                     layerPaths = mDebugLayerPath + ":";
 
-
-                    // If there is a debug layer app specified, add its path.
-                    String gpuDebugLayerApp =
-                            coreSettings.getString(Settings.Global.GPU_DEBUG_LAYER_APP);
-
-                    if (gpuDebugLayerApp != null && !gpuDebugLayerApp.isEmpty()) {
-                        Log.i(TAG, "GPU debug layer app: " + gpuDebugLayerApp);
-                        String paths = getDebugLayerAppPaths(context, gpuDebugLayerApp);
-                        if (paths != null) {
-                            // Append the path so files placed in the app's base directory will
-                            // override the external path
-                            layerPaths += paths + ":";
-                        }
-                    }
-
-                    String layers = coreSettings.getString(Settings.Global.GPU_DEBUG_LAYERS);
+                    String layers = Settings.Global.getString(context.getContentResolver(),
+                                                              Settings.Global.GPU_DEBUG_LAYERS);
 
                     Log.i(TAG, "Debug layer list: " + layers);
                     if (layers != null && !layers.isEmpty()) {
@@ -331,7 +290,6 @@
         return null;
     }
 
-    private static native int getCanLoadSystemLibraries();
     private static native void setLayerPaths(ClassLoader classLoader, String layerPaths);
     private static native void setDebugLayers(String layers);
     private static native void setDriverPath(String path);
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index cd3f301..5d5e5e2 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -19,6 +19,8 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  *
  * Defines a message containing a description and arbitrary data object that can be
@@ -111,7 +113,13 @@
 
     /*package*/ int flags;
 
-    /*package*/ long when;
+    /**
+     * The targeted delivery time of this message. The time-base is
+     * {@link SystemClock#uptimeMillis}.
+     * @hide Only for use within the tests.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public long when;
 
     /*package*/ Bundle data;
 
@@ -382,7 +390,7 @@
      * the <em>target</em> {@link Handler} that is receiving this Message to
      * dispatch it.  If
      * not set, the message will be dispatched to the receiving Handler's
-     * {@link Handler#handleMessage(Message Handler.handleMessage())}.
+     * {@link Handler#handleMessage(Message)}.
      */
     public Runnable getCallback() {
         return callback;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8123744..7ea2008 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2363,7 +2363,6 @@
      */
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS}, conditional = true)
-    @SystemApi
     public @NonNull int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
         try {
             return mService.getProfileIds(userId, enabledOnly);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index aa44eb7..7ffb22f 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -25,7 +25,9 @@
 import com.android.internal.annotations.Immutable;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * System level service for accessing the permission capabilities of the platform.
@@ -40,26 +42,28 @@
      *
      * @hide
      */
-    public static final SplitPermissionInfo[] SPLIT_PERMISSIONS = new SplitPermissionInfo[]{
+    public static final List<SplitPermissionInfo> SPLIT_PERMISSIONS = Arrays.asList(
             // READ_EXTERNAL_STORAGE is always required when an app requests
             // WRITE_EXTERNAL_STORAGE, because we can't have an app that has
             // write access without read access.  The hack here with the target
             // target SDK version ensures that this grant is always done.
             new SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                    new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
+                    Collections.singletonList(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                     android.os.Build.VERSION_CODES.CUR_DEVELOPMENT + 1),
             new SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
-                    new String[]{android.Manifest.permission.READ_CALL_LOG},
+                    Collections.singletonList(android.Manifest.permission.READ_CALL_LOG),
                     android.os.Build.VERSION_CODES.JELLY_BEAN),
             new SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
-                    new String[]{android.Manifest.permission.WRITE_CALL_LOG},
+                    Collections.singletonList(android.Manifest.permission.WRITE_CALL_LOG),
                     android.os.Build.VERSION_CODES.JELLY_BEAN),
             new SplitPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION,
-                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+                    Collections.singletonList(
+                            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                     android.os.Build.VERSION_CODES.P0),
             new SplitPermissionInfo(Manifest.permission.ACCESS_COARSE_LOCATION,
-                    new String[]{android.Manifest.permission.ACCESS_BACKGROUND_LOCATION},
-                    android.os.Build.VERSION_CODES.P0)};
+                    Collections.singletonList(
+                            android.Manifest.permission.ACCESS_BACKGROUND_LOCATION),
+                    android.os.Build.VERSION_CODES.P0));
 
     private final @NonNull Context mContext;
 
@@ -74,7 +78,7 @@
     }
 
     /**
-     * Get list of permissions that have been split into more granular or dependent permissions.
+     * Get set of permissions that have been split into more granular or dependent permissions.
      *
      * <p>E.g. before {@link android.os.Build.VERSION_CODES#P0} an app that was granted
      * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
@@ -82,7 +86,7 @@
      * the location permission only grants location access while the app is in foreground. This
      * would break apps that target before {@link android.os.Build.VERSION_CODES#P0}. Hence whenever
      * such an old app asks for a location permission (i.e. the
-     * {@link SplitPermissionInfo#getRootPermission()}), then the
+     * {@link SplitPermissionInfo#getSplitPermission()}), then the
      * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
      * {@{@link SplitPermissionInfo#getNewPermissions}) is added.
      *
@@ -91,8 +95,9 @@
      *
      * @return All permissions that are split.
      */
-    public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
-        return Arrays.asList(SPLIT_PERMISSIONS);
+    public @NonNull
+    List<SplitPermissionInfo> getSplitPermissions() {
+        return SPLIT_PERMISSIONS;
     }
 
     /**
@@ -101,21 +106,35 @@
      */
     @Immutable
     public static final class SplitPermissionInfo {
-        private final @NonNull String mRootPerm;
-        private final @NonNull String[] mNewPerms;
+        private final @NonNull String mSplitPerm;
+        private final @NonNull List<String> mNewPerms;
         private final int mTargetSdk;
 
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            SplitPermissionInfo that = (SplitPermissionInfo) o;
+            return mTargetSdk == that.mTargetSdk
+                    && Objects.equals(mSplitPerm, that.mSplitPerm);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mSplitPerm, mTargetSdk);
+        }
+
         /**
          * Get the permission that is split.
          */
-        public @NonNull String getRootPermission() {
-            return mRootPerm;
+        public @NonNull String getSplitPermission() {
+            return mSplitPerm;
         }
 
         /**
          * Get the permissions that are added.
          */
-        public @NonNull String[] getNewPermissions() {
+        public @NonNull List<String> getNewPermissions() {
             return mNewPerms;
         }
 
@@ -126,9 +145,9 @@
             return mTargetSdk;
         }
 
-        private SplitPermissionInfo(@NonNull String rootPerm, @NonNull String[] newPerms,
+        private SplitPermissionInfo(@NonNull String rootPerm, @NonNull List<String> newPerms,
                 int targetSdk) {
-            mRootPerm = rootPerm;
+            mSplitPerm = rootPerm;
             mNewPerms = newPerms;
             mTargetSdk = targetSdk;
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c6e4574..acb7577 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11631,12 +11631,6 @@
         public static final String GPU_DEBUG_LAYERS = "gpu_debug_layers";
 
         /**
-         * Addition app for GPU layer discovery
-         * @hide
-         */
-        public static final String GPU_DEBUG_LAYER_APP = "gpu_debug_layer_app";
-
-        /**
          * Control whether the process CPU usage meter should be shown.
          *
          * @deprecated This functionality is no longer available as of
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index b461c0d..7af9db8 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -405,8 +405,8 @@
                 PackageManager.MATCH_SYSTEM_ONLY);
 
         if ((ri == null) || (ri.serviceInfo == null)) {
-            Slog.w(LOG_TAG, String.format("Package or service not found in package %s",
-                    packageName));
+            Slog.w(LOG_TAG, String.format("Package or service not found in package %s for user %d",
+                    packageName, context.getUserId()));
             return null;
         }
         final ServiceInfo si = ri.serviceInfo;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index c89617f..0808cdd 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -23,6 +23,7 @@
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.Rect;
+import android.graphics.text.LineBreaker;
 import android.text.method.TextKeyListener;
 import android.text.style.AlignmentSpan;
 import android.text.style.LeadingMarginSpan;
@@ -50,9 +51,9 @@
 public abstract class Layout {
     /** @hide */
     @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
-            NativeLineBreaker.BREAK_STRATEGY_SIMPLE,
-            NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY,
-            NativeLineBreaker.BREAK_STRATEGY_BALANCED
+            LineBreaker.BREAK_STRATEGY_SIMPLE,
+            LineBreaker.BREAK_STRATEGY_HIGH_QUALITY,
+            LineBreaker.BREAK_STRATEGY_BALANCED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface BreakStrategy {}
@@ -63,20 +64,19 @@
      * before it (which yields a more consistent user experience when editing), but layout may not
      * be the highest quality.
      */
-    public static final int BREAK_STRATEGY_SIMPLE = NativeLineBreaker.BREAK_STRATEGY_SIMPLE;
+    public static final int BREAK_STRATEGY_SIMPLE = LineBreaker.BREAK_STRATEGY_SIMPLE;
 
     /**
      * Value for break strategy indicating high quality line breaking, including automatic
      * hyphenation and doing whole-paragraph optimization of line breaks.
      */
-    public static final int BREAK_STRATEGY_HIGH_QUALITY =
-            NativeLineBreaker.BREAK_STRATEGY_HIGH_QUALITY;
+    public static final int BREAK_STRATEGY_HIGH_QUALITY = LineBreaker.BREAK_STRATEGY_HIGH_QUALITY;
 
     /**
      * Value for break strategy indicating balanced line breaking. The breaks are chosen to
      * make all lines as close to the same length as possible, including automatic hyphenation.
      */
-    public static final int BREAK_STRATEGY_BALANCED = NativeLineBreaker.BREAK_STRATEGY_BALANCED;
+    public static final int BREAK_STRATEGY_BALANCED = LineBreaker.BREAK_STRATEGY_BALANCED;
 
     /** @hide */
     @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
@@ -94,32 +94,29 @@
      * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
      * as suggestions for potential line breaks.
      */
-    public static final int HYPHENATION_FREQUENCY_NONE =
-            NativeLineBreaker.HYPHENATION_FREQUENCY_NONE;
+    public static final int HYPHENATION_FREQUENCY_NONE = LineBreaker.HYPHENATION_FREQUENCY_NONE;
 
     /**
      * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
      * is a conservative default. Useful for informal cases, such as short sentences or chat
      * messages.
      */
-    public static final int HYPHENATION_FREQUENCY_NORMAL =
-            NativeLineBreaker.HYPHENATION_FREQUENCY_NORMAL;
+    public static final int HYPHENATION_FREQUENCY_NORMAL = LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
 
     /**
      * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
      * in typography. Useful for running text and where it's important to put the maximum amount of
      * text in a screen with limited space.
      */
-    public static final int HYPHENATION_FREQUENCY_FULL =
-            NativeLineBreaker.HYPHENATION_FREQUENCY_FULL;
+    public static final int HYPHENATION_FREQUENCY_FULL = LineBreaker.HYPHENATION_FREQUENCY_FULL;
 
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
 
     /** @hide */
     @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = {
-            NativeLineBreaker.JUSTIFICATION_MODE_NONE,
-            NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD
+            LineBreaker.JUSTIFICATION_MODE_NONE,
+            LineBreaker.JUSTIFICATION_MODE_INTER_WORD
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface JustificationMode {}
@@ -127,13 +124,13 @@
     /**
      * Value for justification mode indicating no justification.
      */
-    public static final int JUSTIFICATION_MODE_NONE = NativeLineBreaker.JUSTIFICATION_MODE_NONE;
+    public static final int JUSTIFICATION_MODE_NONE = LineBreaker.JUSTIFICATION_MODE_NONE;
 
     /**
      * Value for justification mode indicating the text is justified by stretching word spacing.
      */
     public static final int JUSTIFICATION_MODE_INTER_WORD =
-            NativeLineBreaker.JUSTIFICATION_MODE_INTER_WORD;
+            LineBreaker.JUSTIFICATION_MODE_INTER_WORD;
 
     /*
      * Line spacing multiplier for default line spacing.
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 9bf8cd2..0a2d65c 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.text.MeasuredText;
 import android.text.AutoGrowArray.ByteArray;
 import android.text.AutoGrowArray.FloatArray;
 import android.text.AutoGrowArray.IntArray;
@@ -121,7 +122,7 @@
     private @Nullable IntArray mFontMetrics = new IntArray(4 * 4);
 
     // The native MeasuredParagraph.
-    private @Nullable NativeMeasuredParagraph mNativeMeasuredParagraph;
+    private @Nullable MeasuredText mMeasuredText;
 
     // Following two objects are for avoiding object allocation.
     private @NonNull TextPaint mCachedPaint = new TextPaint();
@@ -149,7 +150,7 @@
         mWidths.clear();
         mFontMetrics.clear();
         mSpanEndCache.clear();
-        mNativeMeasuredParagraph = null;
+        mMeasuredText = null;
     }
 
     /**
@@ -245,8 +246,8 @@
      * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
      * Returns null in other cases.
      */
-    public NativeMeasuredParagraph getNativeMeasuredParagraph() {
-        return mNativeMeasuredParagraph;
+    public MeasuredText getMeasuredText() {
+        return mMeasuredText;
     }
 
     /**
@@ -259,7 +260,7 @@
      * @param end the exclusive end offset of the target region in the text
      */
     public float getWidth(int start, int end) {
-        if (mNativeMeasuredParagraph == null) {
+        if (mMeasuredText == null) {
             // We have result in Java.
             final float[] widths = mWidths.getRawArray();
             float r = 0.0f;
@@ -269,7 +270,7 @@
             return r;
         } else {
             // We have result in native.
-            return mNativeMeasuredParagraph.getWidth(start, end);
+            return mMeasuredText.getWidth(start, end);
         }
     }
 
@@ -281,7 +282,7 @@
      */
     public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
             @NonNull Rect bounds) {
-        mNativeMeasuredParagraph.getBounds(mCopiedBuffer, start, end, bounds);
+        mMeasuredText.getBounds(start, end, bounds);
     }
 
     /**
@@ -290,7 +291,7 @@
      * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
      */
     public float getCharWidthAt(@IntRange(from = 0) int offset) {
-        return mNativeMeasuredParagraph.getCharWidthAt(offset);
+        return mMeasuredText.getCharWidthAt(offset);
     }
 
     /**
@@ -391,12 +392,13 @@
             @Nullable MeasuredParagraph recycle) {
         final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
         mt.resetAndAnalyzeBidi(text, start, end, textDir);
-        final NativeMeasuredParagraph.Builder builder = new NativeMeasuredParagraph.Builder();
+        final MeasuredText.Builder builder = new MeasuredText.Builder(mt.mCopiedBuffer);
+        builder.setComputeHyphenation(computeHyphenation);
+        builder.setComputeLayout(computeLayout);
         if (mt.mTextLength == 0) {
             // Need to build empty native measured text for StaticLayout.
             // TODO: Stop creating empty measured text for empty lines.
-            mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation,
-                        computeLayout);
+            mt.mMeasuredText = builder.build();
         } else {
             if (mt.mSpanned == null) {
                 // No style change by MetricsAffectingSpan. Just measure all text.
@@ -417,8 +419,7 @@
                     mt.mSpanEndCache.append(spanEnd);
                 }
             }
-            mt.mNativeMeasuredParagraph = builder.build(mt.mCopiedBuffer, computeHyphenation,
-                    computeLayout);
+            mt.mMeasuredText = builder.build();
         }
 
         return mt;
@@ -490,7 +491,7 @@
     private void applyReplacementRun(@NonNull ReplacementSpan replacement,
                                      @IntRange(from = 0) int start,  // inclusive, in copied buffer
                                      @IntRange(from = 0) int end,  // exclusive, in copied buffer
-                                     @Nullable NativeMeasuredParagraph.Builder builder) {
+                                     @Nullable MeasuredText.Builder builder) {
         // Use original text. Shouldn't matter.
         // TODO: passing uninitizlied FontMetrics to developers. Do we need to keep this for
         //       backward compatibility? or Should we initialize them for getFontMetricsInt?
@@ -510,7 +511,7 @@
 
     private void applyStyleRun(@IntRange(from = 0) int start,  // inclusive, in copied buffer
                                @IntRange(from = 0) int end,  // exclusive, in copied buffer
-                               @Nullable NativeMeasuredParagraph.Builder builder) {
+                               @Nullable MeasuredText.Builder builder) {
 
         if (mLtrWithoutBidi) {
             // If the whole text is LTR direction, just apply whole region.
@@ -552,7 +553,7 @@
             @Nullable MetricAffectingSpan[] spans,
             @IntRange(from = 0) int start,  // inclusive, in original text buffer
             @IntRange(from = 0) int end,  // exclusive, in original text buffer
-            @Nullable NativeMeasuredParagraph.Builder builder) {
+            @Nullable MeasuredText.Builder builder) {
         mCachedPaint.set(paint);
         // XXX paint should not have a baseline shift, but...
         mCachedPaint.baselineShift = 0;
@@ -658,6 +659,6 @@
      * This only works if the MeasuredParagraph is computed with buildForStaticLayout.
      */
     public @IntRange(from = 0) int getMemoryUsage() {
-        return mNativeMeasuredParagraph.getMemoryUsage();
+        return mMeasuredText.getMemoryUsage();
     }
 }
diff --git a/core/java/android/text/NativeMeasuredParagraph.java b/core/java/android/text/NativeMeasuredParagraph.java
deleted file mode 100644
index bfdccca..0000000
--- a/core/java/android/text/NativeMeasuredParagraph.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2010 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.text;
-
-import android.annotation.FloatRange;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.graphics.Paint;
-import android.graphics.Rect;
-
-import dalvik.annotation.optimization.CriticalNative;
-
-import libcore.util.NativeAllocationRegistry;
-
-/**
- * A native implementation of measured paragraph.
- * TODO: Consider to make this class public.
- * @hide
- */
-public class NativeMeasuredParagraph {
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            NativeMeasuredParagraph.class.getClassLoader(), nGetReleaseFunc(), 1024);
-
-    private long mNativePtr;
-    private @NonNull char[] mChars;
-
-    // Use builder instead.
-    private NativeMeasuredParagraph(long ptr, @NonNull char[] chars) {
-        mNativePtr = ptr;
-        mChars = chars;
-    }
-
-    /**
-     * Returns a characters of this paragraph.
-     */
-    public char[] getChars() {
-        return mChars;
-    }
-
-    /**
-     * Returns a width of the given region
-     */
-    public float getWidth(int start, int end) {
-        return nGetWidth(mNativePtr, start, end);
-    }
-
-    /**
-     * Returns a memory usage of the native object.
-     */
-    public int getMemoryUsage() {
-        return nGetMemoryUsage(mNativePtr);
-    }
-
-    /**
-     * Fills the boundary box of the given region
-     */
-    public void getBounds(char[] buf, int start, int end, Rect rect) {
-        nGetBounds(mNativePtr, buf, start, end, rect);
-    }
-
-    /**
-     * Returns the width of the character at the given offset
-     */
-    public float getCharWidthAt(int offset) {
-        return nGetCharWidthAt(mNativePtr, offset);
-    }
-
-    /**
-     * Returns a native pointer of the underlying native object.
-     */
-    public long getNativePtr() {
-        return mNativePtr;
-    }
-
-    @CriticalNative
-    private static native float nGetWidth(/* Non Zero */ long nativePtr,
-                                         @IntRange(from = 0) int start,
-                                         @IntRange(from = 0) int end);
-
-    @CriticalNative
-    private static native /* Non Zero */ long nGetReleaseFunc();
-
-    @CriticalNative
-    private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr);
-
-    private static native void nGetBounds(long nativePtr, char[] buf, int start, int end,
-            Rect rect);
-
-    @CriticalNative
-    private static native float nGetCharWidthAt(long nativePtr, int offset);
-
-    /**
-     * A builder for the NativeMeasuredParagraph
-     */
-    public static class Builder {
-        private final long mNativePtr;
-
-        public Builder() {
-            mNativePtr = nInitBuilder();
-        }
-
-        /**
-         * Apply styles to given range
-         */
-        public void addStyleRun(@NonNull Paint paint, int start, int end, boolean isRtl) {
-            nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl);
-        }
-
-        /**
-         * Tells native that the given range is replaced with the object of given width.
-         */
-        public void addReplacementRun(@NonNull Paint paint, int start, int end, float width) {
-            nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width);
-        }
-
-        /**
-         * Build the NativeMeasuredParagraph
-         */
-        public NativeMeasuredParagraph build(char[] text, boolean computeHyphenation,
-                boolean computeLayout) {
-            try {
-                long ptr = nBuildNativeMeasuredParagraph(mNativePtr, text, computeHyphenation,
-                        computeLayout);
-                NativeMeasuredParagraph res = new NativeMeasuredParagraph(ptr, text);
-                sRegistry.registerNativeAllocation(res, ptr);
-                return res;
-            } finally {
-                nFreeBuilder(mNativePtr);
-            }
-        }
-
-        private static native /* Non Zero */ long nInitBuilder();
-
-        /**
-         * Apply style to make native measured text.
-         *
-         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
-         * @param paintPtr The native paint pointer to be applied.
-         * @param start The start offset in the copied buffer.
-         * @param end The end offset in the copied buffer.
-         * @param isRtl True if the text is RTL.
-         */
-        private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr,
-                                                /* Non Zero */ long paintPtr,
-                                                @IntRange(from = 0) int start,
-                                                @IntRange(from = 0) int end,
-                                                boolean isRtl);
-        /**
-         * Apply ReplacementRun to make native measured text.
-         *
-         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
-         * @param paintPtr The native paint pointer to be applied.
-         * @param start The start offset in the copied buffer.
-         * @param end The end offset in the copied buffer.
-         * @param width The width of the replacement.
-         */
-        private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr,
-                                                      /* Non Zero */ long paintPtr,
-                                                      @IntRange(from = 0) int start,
-                                                      @IntRange(from = 0) int end,
-                                                      @FloatRange(from = 0) float width);
-
-        private static native long nBuildNativeMeasuredParagraph(
-                /* Non Zero */ long nativeBuilderPtr,
-                @NonNull char[] text,
-                boolean computeHyphenation,
-                boolean computeLayout);
-
-        private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
-    }
-}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index d2f0853..ac7e574 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Paint;
+import android.graphics.text.LineBreaker;
 import android.os.Build;
 import android.text.style.LeadingMarginSpan;
 import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;
@@ -55,7 +56,7 @@
      *
      *   - Create MeasuredParagraph by MeasuredParagraph.buildForStaticLayout which measures in
      *     native.
-     *   - Run NativeLineBreaker.computeLineBreaks() to obtain line breaks for the paragraph.
+     *   - Run LineBreaker.computeLineBreaks() to obtain line breaks for the paragraph.
      *
      * After all paragraphs, call finish() to release expensive buffers.
      */
@@ -634,7 +635,7 @@
             indents = null;
         }
 
-        final NativeLineBreaker lineBreaker = new NativeLineBreaker.Builder()
+        final LineBreaker lineBreaker = new LineBreaker.Builder()
                 .setBreakStrategy(b.mBreakStrategy)
                 .setHyphenationFrequency(b.mHyphenationFrequency)
                 // TODO: Support more justification mode, e.g. letter spacing, stretching.
@@ -642,8 +643,8 @@
                 .setIndents(indents)
                 .build();
 
-        NativeLineBreaker.ParagraphConstraints constraints =
-                new NativeLineBreaker.ParagraphConstraints();
+        LineBreaker.ParagraphConstraints constraints =
+                new LineBreaker.ParagraphConstraints();
 
         PrecomputedText.ParagraphInfo[] paragraphInfo = null;
         final Spanned spanned = (source instanceof Spanned) ? (Spanned) source : null;
@@ -739,8 +740,8 @@
             constraints.setIndent(firstWidth, firstWidthLineCount);
             constraints.setTabStops(variableTabStops, TAB_INCREMENT);
 
-            NativeLineBreaker.Result res = lineBreaker.computeLineBreaks(
-                    measuredPara.getNativeMeasuredParagraph(), constraints, mLineCount);
+            LineBreaker.Result res = lineBreaker.computeLineBreaks(
+                    measuredPara.getMeasuredText(), constraints, mLineCount);
             int breakCount = res.getLineCount();
             if (lineBreakCapacity < breakCount) {
                 lineBreakCapacity = breakCount;
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index 2dc4f60..648bd1b 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -29,8 +29,33 @@
 import android.text.TextUtils;
 
 /**
- * Sets the text color, size, style, and typeface to match a TextAppearance
- * resource.
+ * Sets the text appearance using the given
+ * {@link android.R.styleable#TextAppearance TextAppearance} attributes.
+ * By default {@link TextAppearanceSpan} only changes the specified attributes in XML.
+ * {@link android.R.styleable#TextAppearance_textColorHighlight textColorHighlight},
+ * {@link android.R.styleable#TextAppearance_textColorHint textColorHint},
+ * {@link android.R.styleable#TextAppearance_textAllCaps textAllCaps} and
+ * {@link android.R.styleable#TextAppearance_fallbackLineSpacing fallbackLineSpacing}
+ * are not supported by {@link TextAppearanceSpan}.
+ *
+ * {@see android.widget.TextView#setTextAppearance(int)}
+ *
+ * @attr ref android.R.styleable#TextAppearance_fontFamily
+ * @attr ref android.R.styleable#TextAppearance_textColor
+ * @attr ref android.R.styleable#TextAppearance_textColorLink
+ * @attr ref android.R.styleable#TextAppearance_textFontWeight
+ * @attr ref android.R.styleable#TextAppearance_textSize
+ * @attr ref android.R.styleable#TextAppearance_textStyle
+ * @attr ref android.R.styleable#TextAppearance_typeface
+ * @attr ref android.R.styleable#TextAppearance_shadowColor
+ * @attr ref android.R.styleable#TextAppearance_shadowDx
+ * @attr ref android.R.styleable#TextAppearance_shadowDy
+ * @attr ref android.R.styleable#TextAppearance_shadowRadius
+ * @attr ref android.R.styleable#TextAppearance_elegantTextHeight
+ * @attr ref android.R.styleable#TextAppearance_letterSpacing
+ * @attr ref android.R.styleable#TextAppearance_fontFeatureSettings
+ * @attr ref android.R.styleable#TextAppearance_fontVariationSettings
+ *
  */
 public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
     private final String mFamilyName;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 319f080..bd2bef4 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -25,6 +25,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
 
 import com.android.internal.R;
 
@@ -413,7 +414,6 @@
             }
         }
         final int finalVisibility = endVisibility;
-        final ViewGroup finalSceneRoot = sceneRoot;
 
         if (overlayView != null) {
             // TODO: Need to do this for general case of adding to overlay
@@ -424,16 +424,32 @@
             sceneRoot.getLocationOnScreen(loc);
             overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
             overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
-            sceneRoot.getOverlay().add(overlayView);
+            final ViewGroupOverlay overlay = sceneRoot.getOverlay();
+            overlay.add(overlayView);
             Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
             if (animator == null) {
-                sceneRoot.getOverlay().remove(overlayView);
+                overlay.remove(overlayView);
             } else {
                 final View finalOverlayView = overlayView;
                 addListener(new TransitionListenerAdapter() {
+
+                    @Override
+                    public void onTransitionPause(Transition transition) {
+                        overlay.remove(finalOverlayView);
+                    }
+
+                    @Override
+                    public void onTransitionResume(Transition transition) {
+                        if (finalOverlayView.getParent() == null) {
+                            overlay.add(finalOverlayView);
+                        } else {
+                            cancel();
+                        }
+                    }
+
                     @Override
                     public void onTransitionEnd(Transition transition) {
-                        finalSceneRoot.getOverlay().remove(finalOverlayView);
+                        overlay.remove(finalOverlayView);
                         transition.removeListener(this);
                     }
                 });
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index f428c79..e9f1edf 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -245,9 +245,8 @@
      *                   passed, it's treated as an empty rectangle (0,0)-(0,0).
      */
     // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
-    public DisplayCutout(
-            Insets safeInsets, @Nullable Rect boundLeft, @Nullable Rect boundTop,
-            @Nullable Rect boundRight, @Nullable Rect boundBottom) {
+    public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
+            @Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom) {
         this(safeInsets.toRect(), boundLeft, boundTop, boundRight, boundBottom, true);
     }
 
@@ -262,7 +261,7 @@
      */
     // TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
     @Deprecated
-    public DisplayCutout(Rect safeInsets, List<Rect> boundingRects) {
+    public DisplayCutout(@Nullable Rect safeInsets, @Nullable List<Rect> boundingRects) {
         this(safeInsets, extractBoundsFromList(safeInsets, boundingRects),
                 true /* copyArguments */);
     }
@@ -313,18 +312,20 @@
         for (int i = 0; i < sortedBounds.length; ++i) {
             sortedBounds[i] = ZERO_RECT;
         }
-        for (Rect bound : boundingRects) {
-            // There will be at most one non-functional area per short edge of the device, and none
-            // on the long edges, so either safeInsets.right or safeInsets.bottom must be 0.
-            // TODO(b/117199965): Refine the logic to handle edge cases.
-            if (bound.left == 0) {
-                sortedBounds[BOUNDS_POSITION_LEFT] = bound;
-            } else if (bound.top == 0) {
-                sortedBounds[BOUNDS_POSITION_TOP] = bound;
-            } else if (safeInsets.right > 0) {
-                sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
-            } else if (safeInsets.bottom > 0) {
-                sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+        if (safeInsets != null && boundingRects != null) {
+            for (Rect bound : boundingRects) {
+                // There is at most one non-functional area per short edge of the device, but none
+                // on the long edges, so either safeInsets.right or safeInsets.bottom must be 0.
+                // TODO(b/117199965): Refine the logic to handle edge cases.
+                if (bound.left == 0) {
+                    sortedBounds[BOUNDS_POSITION_LEFT] = bound;
+                } else if (bound.top == 0) {
+                    sortedBounds[BOUNDS_POSITION_TOP] = bound;
+                } else if (safeInsets.right > 0) {
+                    sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
+                } else if (safeInsets.bottom > 0) {
+                    sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+                }
             }
         }
         return sortedBounds;
@@ -389,6 +390,7 @@
      * @return a list of bounding {@code Rect}s, one for each display cutout area. No empty Rect is
      * returned.
      */
+    @NonNull
     public List<Rect> getBoundingRects() {
         List<Rect> result = new ArrayList<>();
         for (Rect bound : getBoundingRectsAll()) {
diff --git a/core/java/android/view/TouchDelegate.java b/core/java/android/view/TouchDelegate.java
index b361ab4..06b73dd 100644
--- a/core/java/android/view/TouchDelegate.java
+++ b/core/java/android/view/TouchDelegate.java
@@ -16,8 +16,12 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.ArrayMap;
+import android.view.accessibility.AccessibilityNodeInfo.TouchDelegateInfo;
 
 /**
  * Helper class to handle situations where you want a view to have a larger touch area than its
@@ -78,6 +82,11 @@
     private int mSlop;
 
     /**
+     * Touch delegate information for accessibility
+     */
+    private TouchDelegateInfo mTouchDelegateInfo;
+
+    /**
      * Constructor
      *
      * @param bounds Bounds in local coordinates of the containing view that should be mapped to
@@ -145,4 +154,20 @@
         }
         return handled;
     }
+
+    /**
+     * Return a {@link TouchDelegateInfo} mapping from regions (in view coordinates) to
+     * delegated views for accessibility usage.
+     *
+     * @return A TouchDelegateInfo.
+     */
+    @NonNull
+    public TouchDelegateInfo getTouchDelegateInfo() {
+        if (mTouchDelegateInfo == null) {
+            final ArrayMap<Region, View> targetMap = new ArrayMap<>(1);
+            targetMap.put(new Region(mBounds), mDelegateView);
+            mTouchDelegateInfo = new TouchDelegateInfo(targetMap);
+        }
+        return mTouchDelegateInfo;
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1ed6203..29d3742 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7315,17 +7315,16 @@
         // Here we check whether we still need the default focus highlight, and switch it on/off.
         switchDefaultFocusHighlight();
 
-        InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
         if (!gainFocus) {
             if (isPressed()) {
                 setPressed(false);
             }
-            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
-                imm.focusOut(this);
+            if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
+                notifyFocusChangeToInputMethodManager(false /* hasFocus */);
             }
             onFocusLost();
-        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
-            imm.focusIn(this);
+        } else if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
+            notifyFocusChangeToInputMethodManager(true /* hasFocus */);
         }
 
         invalidate(true);
@@ -7341,6 +7340,26 @@
         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
     }
 
+    /**
+     * Notify {@link InputMethodManager} about the focus change of the {@link View}.
+     *
+     * <p>Does nothing when {@link InputMethodManager} is not available.</p>
+     *
+     * @param hasFocus {@code true} when the {@link View} is being focused.
+     */
+    private void notifyFocusChangeToInputMethodManager(boolean hasFocus) {
+        final InputMethodManager imm =
+                getContext().getSystemService(InputMethodManager.class);
+        if (imm == null) {
+            return;
+        }
+        if (hasFocus) {
+            imm.focusIn(this);
+        } else {
+            imm.focusOut(this);
+        }
+    }
+
     /** @hide */
     public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
         if (canNotifyAutofillEnterExitEvent()) {
@@ -8881,6 +8900,10 @@
         populateAccessibilityNodeInfoDrawingOrderInParent(info);
         info.setPaneTitle(mAccessibilityPaneTitle);
         info.setHeading(isAccessibilityHeading());
+
+        if (mTouchDelegate != null) {
+            info.setTouchDelegateInfo(mTouchDelegate.getTouchDelegateInfo());
+        }
     }
 
     /**
@@ -12481,7 +12504,7 @@
         mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
         onFinishTemporaryDetach();
         if (hasWindowFocus() && hasFocus()) {
-            getContext().getSystemService(InputMethodManager.class).focusIn(this);
+            notifyFocusChangeToInputMethodManager(true /* hasFocus */);
         }
         notifyEnterOrExitForAutoFillIfNeeded(true);
     }
@@ -12872,20 +12895,19 @@
      *        focus, false otherwise.
      */
     public void onWindowFocusChanged(boolean hasWindowFocus) {
-        InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
         if (!hasWindowFocus) {
             if (isPressed()) {
                 setPressed(false);
             }
             mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
-            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
-                imm.focusOut(this);
+            if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+                notifyFocusChangeToInputMethodManager(false /* hasFocus */);
             }
             removeLongPressCallback();
             removeTapCallback();
             onFocusLost();
-        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
-            imm.focusIn(this);
+        } else if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
+            notifyFocusChangeToInputMethodManager(true /* hasFocus */);
         }
 
         refreshDrawableState();
@@ -17977,10 +17999,7 @@
         rebuildOutline();
 
         if (isFocused()) {
-            InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
-            if (imm != null) {
-                imm.focusIn(this);
-            }
+            notifyFocusChangeToInputMethodManager(true /* hasFocus */);
         }
     }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 982737a..c1e94d8 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1085,6 +1085,19 @@
      *
      * <p>Refer to the individual flags for the permissions needed.
      *
+     * @param flags The flag bits to add.
+     *
+     * @hide
+     */
+    public void addPrivateFlags(int flags) {
+        setPrivateFlags(flags, flags);
+    }
+
+    /**
+     * Add system flag bits.
+     *
+     * <p>Refer to the individual flags for the permissions needed.
+     *
      * <p>Note: Only for updateable system components (aka. mainline modules)
      *
      * @param flags The flag bits to add.
@@ -1092,8 +1105,8 @@
      * @hide
      */
     @SystemApi
-    public void addPrivateFlags(int flags) {
-        setPrivateFlags(flags, flags);
+    public void addSystemFlags(@WindowManager.LayoutParams.SystemFlags int flags) {
+        addPrivateFlags(flags);
     }
 
     /**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 742df5e8..2d77cb4 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1670,7 +1670,7 @@
          */
         @SystemApi
         @RequiresPermission(permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
-        public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
+        public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
 
         /**
          * Indicates that this window is the rounded corners overlay present on some
@@ -1708,6 +1708,18 @@
         public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 0x00800000;
 
         /**
+         * An internal annotation for flags that can be specified to {@link #softInputMode}.
+         *
+         * @hide
+         */
+        @SystemApi
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = {
+                SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+        })
+        public @interface SystemFlags {}
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
@@ -1781,8 +1793,8 @@
                         equals = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE,
                         name = "SUSTAINED_PERFORMANCE_MODE"),
                 @ViewDebug.FlagToString(
-                        mask = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
-                        equals = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+                        mask = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
+                        equals = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
                         name = "HIDE_NON_SYSTEM_OVERLAY_WINDOWS"),
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 4d3f0fc..e129091 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -23,10 +23,12 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -39,17 +41,21 @@
 import android.text.style.AccessibilityURLSpan;
 import android.text.style.ClickableSpan;
 import android.text.style.URLSpan;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
+import android.view.TouchDelegate;
 import android.view.View;
 
 import com.android.internal.R;
 import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -748,6 +754,8 @@
     private CollectionInfo mCollectionInfo;
     private CollectionItemInfo mCollectionItemInfo;
 
+    private TouchDelegateInfo mTouchDelegateInfo;
+
     /**
      * Hide constructor from clients.
      */
@@ -810,7 +818,7 @@
     public AccessibilityNodeInfo findFocus(int focus) {
         enforceSealed();
         enforceValidFocusType(focus);
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return null;
         }
         return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
@@ -834,7 +842,7 @@
     public AccessibilityNodeInfo focusSearch(int direction) {
         enforceSealed();
         enforceValidFocusDirection(direction);
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return null;
         }
         return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
@@ -866,7 +874,7 @@
     @UnsupportedAppUsage
     public boolean refresh(Bundle arguments, boolean bypassCache) {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return false;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -967,7 +975,7 @@
         if (mChildNodeIds == null) {
             return null;
         }
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return null;
         }
         final long childId = mChildNodeIds.get(index);
@@ -1271,7 +1279,7 @@
      */
     public AccessibilityNodeInfo getTraversalBefore() {
         enforceSealed();
-        return getNodeForAccessibilityId(mTraversalBefore);
+        return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalBefore);
     }
 
     /**
@@ -1332,7 +1340,7 @@
      */
     public AccessibilityNodeInfo getTraversalAfter() {
         enforceSealed();
-        return getNodeForAccessibilityId(mTraversalAfter);
+        return getNodeForAccessibilityId(mConnectionId, mWindowId, mTraversalAfter);
     }
 
     /**
@@ -1489,7 +1497,7 @@
      */
     public boolean performAction(int action) {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return false;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1512,7 +1520,7 @@
      */
     public boolean performAction(int action, Bundle arguments) {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return false;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1536,7 +1544,7 @@
      */
     public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return Collections.emptyList();
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1567,7 +1575,7 @@
      */
     public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return Collections.emptyList();
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1584,7 +1592,7 @@
      */
     public AccessibilityWindowInfo getWindow() {
         enforceSealed();
-        if (!canPerformRequestOverConnection(mSourceNodeId)) {
+        if (!canPerformRequestOverConnection(mConnectionId, mWindowId, mSourceNodeId)) {
             return null;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
@@ -1603,7 +1611,7 @@
      */
     public AccessibilityNodeInfo getParent() {
         enforceSealed();
-        return getNodeForAccessibilityId(mParentNodeId);
+        return getNodeForAccessibilityId(mConnectionId, mWindowId, mParentNodeId);
     }
 
     /**
@@ -2783,7 +2791,7 @@
      */
     public AccessibilityNodeInfo getLabelFor() {
         enforceSealed();
-        return getNodeForAccessibilityId(mLabelForId);
+        return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabelForId);
     }
 
     /**
@@ -2835,7 +2843,7 @@
      */
     public AccessibilityNodeInfo getLabeledBy() {
         enforceSealed();
-        return getNodeForAccessibilityId(mLabeledById);
+        return getNodeForAccessibilityId(mConnectionId, mWindowId, mLabeledById);
     }
 
     /**
@@ -2975,6 +2983,43 @@
     }
 
     /**
+     * Get the {@link TouchDelegateInfo} for touch delegate behavior with the represented view.
+     * It is possible for the same node to be pointed to by several regions. Use
+     * {@link TouchDelegateInfo#getRegionAt(int)} to get touch delegate target {@link Region}, and
+     * {@link TouchDelegateInfo#getTargetForRegion(Region)} for {@link AccessibilityNodeInfo} from
+     * the given region.
+     *
+     * @return {@link TouchDelegateInfo} or {@code null} if there are no touch delegates.
+     */
+    @Nullable
+    public TouchDelegateInfo getTouchDelegateInfo() {
+        if (mTouchDelegateInfo != null) {
+            mTouchDelegateInfo.setConnectionId(mConnectionId);
+            mTouchDelegateInfo.setWindowId(mWindowId);
+        }
+        return mTouchDelegateInfo;
+    }
+
+    /**
+     * Set touch delegate info if the represented view has a {@link TouchDelegate}.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an
+     *   AccessibilityService.
+     * </p>
+     *
+     * @param delegatedInfo {@link TouchDelegateInfo} returned from
+     *         {@link TouchDelegate#getTouchDelegateInfo()}.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setTouchDelegateInfo(@NonNull TouchDelegateInfo delegatedInfo) {
+        enforceNotSealed();
+        mTouchDelegateInfo = delegatedInfo;
+    }
+
+    /**
      * Gets the value of a boolean property.
      *
      * @param property The property.
@@ -3340,6 +3385,10 @@
         if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
             nonDefaultFields |= bitAt(fieldIndex);
         }
+        fieldIndex++;
+        if (!Objects.equals(mTouchDelegateInfo, DEFAULT.mTouchDelegateInfo)) {
+            nonDefaultFields |= bitAt(fieldIndex);
+        }
         int totalFields = fieldIndex;
         parcel.writeLong(nonDefaultFields);
 
@@ -3462,6 +3511,10 @@
             parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
         }
 
+        if (isBitSet(nonDefaultFields, fieldIndex++)) {
+            mTouchDelegateInfo.writeToParcel(parcel, flags);
+        }
+
         if (DEBUG) {
             fieldIndex--;
             if (totalFields != fieldIndex) {
@@ -3543,6 +3596,10 @@
         if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
         mCollectionItemInfo =  (other.mCollectionItemInfo != null)
                 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
+
+        final TouchDelegateInfo otherInfo = other.mTouchDelegateInfo;
+        mTouchDelegateInfo = (otherInfo != null)
+                ? new TouchDelegateInfo(otherInfo.mTargetMap, true) : null;
     }
 
     /**
@@ -3665,6 +3722,10 @@
                         parcel.readInt() == 1)
                 : null;
 
+        if (isBitSet(nonDefaultFields, fieldIndex++)) {
+            mTouchDelegateInfo = TouchDelegateInfo.CREATOR.createFromParcel(parcel);
+        }
+
         mSealed = sealed;
     }
 
@@ -3813,10 +3874,11 @@
         }
     }
 
-    private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
-        return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
+    private static boolean canPerformRequestOverConnection(int connectionId,
+            int windowId, long accessibilityNodeId) {
+        return ((windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
                 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
-                && (mConnectionId != UNDEFINED_CONNECTION_ID));
+                && (connectionId != UNDEFINED_CONNECTION_ID));
     }
 
     @Override
@@ -3919,13 +3981,14 @@
         return builder.toString();
     }
 
-    private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
-        if (!canPerformRequestOverConnection(accessibilityId)) {
+    private static AccessibilityNodeInfo getNodeForAccessibilityId(int connectionId,
+            int windowId, long accessibilityId) {
+        if (!canPerformRequestOverConnection(connectionId, windowId, accessibilityId)) {
             return null;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
-                mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
+        return client.findAccessibilityNodeInfoByAccessibilityId(connectionId,
+                windowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
                         | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
     }
 
@@ -4896,6 +4959,176 @@
     }
 
     /**
+     * Class with information of touch delegated views and regions from {@link TouchDelegate} for
+     * the {@link AccessibilityNodeInfo}.
+     *
+     * @see AccessibilityNodeInfo#setTouchDelegateInfo(TouchDelegateInfo)
+     */
+    public static final class TouchDelegateInfo implements Parcelable {
+        private ArrayMap<Region, Long> mTargetMap;
+        // Two ids are initialized lazily in AccessibilityNodeInfo#getTouchDelegateInfo
+        private int mConnectionId;
+        private int mWindowId;
+
+        /**
+         * Create a new instance of {@link TouchDelegateInfo}.
+         *
+         * @param targetMap A map from regions (in view coordinates) to delegated views.
+         * @throws IllegalArgumentException if targetMap is empty or {@code null} in
+         * Regions or Views.
+         */
+        public TouchDelegateInfo(@NonNull Map<Region, View> targetMap) {
+            Preconditions.checkArgument(!targetMap.isEmpty()
+                    && !targetMap.containsKey(null) && !targetMap.containsValue(null));
+            mTargetMap = new ArrayMap<>(targetMap.size());
+            for (final Region region : targetMap.keySet()) {
+                final View view = targetMap.get(region);
+                mTargetMap.put(region, (long) view.getAccessibilityViewId());
+            }
+        }
+
+        /**
+         * Create a new instance from target map.
+         *
+         * @param targetMap A map from regions (in view coordinates) to delegated views'
+         *                  accessibility id.
+         * @param doCopy True if shallow copy targetMap.
+         * @throws IllegalArgumentException if targetMap is empty or {@code null} in
+         * Regions or Views.
+         */
+        TouchDelegateInfo(@NonNull ArrayMap<Region, Long> targetMap, boolean doCopy) {
+            Preconditions.checkArgument(!targetMap.isEmpty()
+                    && !targetMap.containsKey(null) && !targetMap.containsValue(null));
+            if (doCopy) {
+                mTargetMap = new ArrayMap<>(targetMap.size());
+                mTargetMap.putAll(targetMap);
+            } else {
+                mTargetMap = targetMap;
+            }
+        }
+
+        /**
+         * Set the connection ID.
+         *
+         * @param connectionId The connection id.
+         */
+        private void setConnectionId(int connectionId) {
+            mConnectionId = connectionId;
+        }
+
+        /**
+         * Set the window ID.
+         *
+         * @param windowId The window id.
+         */
+        private void setWindowId(int windowId) {
+            mWindowId = windowId;
+        }
+
+        /**
+         * Returns the number of touch delegate target region.
+         *
+         * @return Number of touch delegate target region.
+         */
+        public int getRegionCount() {
+            return mTargetMap.size();
+        }
+
+        /**
+         * Return the {@link Region} at the given index in the {@link TouchDelegateInfo}.
+         *
+         * @param index The desired index, must be between 0 and {@link #getRegionCount()}-1.
+         * @return Returns the {@link Region} stored at the given index.
+         */
+        @NonNull
+        public Region getRegionAt(int index) {
+            return mTargetMap.keyAt(index);
+        }
+
+        /**
+         * Return the target {@link AccessibilityNodeInfo} for the given {@link Region}.
+         * <p>
+         *   <strong>Note:</strong> This api can only be called from {@link AccessibilityService}.
+         * </p>
+         * <p>
+         *   <strong>Note:</strong> It is a client responsibility to recycle the
+         *     received info by calling {@link AccessibilityNodeInfo#recycle()}
+         *     to avoid creating of multiple instances.
+         * </p>
+         *
+         * @param region The region retrieved from {@link #getRegionAt(int)}.
+         * @return The target node associates with the given region.
+         */
+        @Nullable
+        public AccessibilityNodeInfo getTargetForRegion(@NonNull Region region) {
+            return getNodeForAccessibilityId(mConnectionId, mWindowId, mTargetMap.get(region));
+        }
+
+        /**
+         * Return the accessibility id of target node.
+         *
+         * @param region The region retrieved from {@link #getRegionAt(int)}.
+         * @return The accessibility id of target node.
+         *
+         * @hide
+         */
+        @TestApi
+        public long getAccessibilityIdForRegion(@NonNull Region region) {
+            return mTargetMap.get(region);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mTargetMap.size());
+            for (int i = 0; i < mTargetMap.size(); i++) {
+                final Region region = mTargetMap.keyAt(i);
+                final Long accessibilityId = mTargetMap.valueAt(i);
+                region.writeToParcel(dest, flags);
+                dest.writeLong(accessibilityId);
+            }
+        }
+
+        /**
+         * @see android.os.Parcelable.Creator
+         */
+        public static final Parcelable.Creator<TouchDelegateInfo> CREATOR =
+                new Parcelable.Creator<TouchDelegateInfo>() {
+            @Override
+            public TouchDelegateInfo createFromParcel(Parcel parcel) {
+                final int size = parcel.readInt();
+                if (size == 0) {
+                    return null;
+                }
+                final ArrayMap<Region, Long> targetMap = new ArrayMap<>(size);
+                for (int i = 0; i < size; i++) {
+                    final Region region = Region.CREATOR.createFromParcel(parcel);
+                    final long accessibilityId = parcel.readLong();
+                    targetMap.put(region, accessibilityId);
+                }
+                final TouchDelegateInfo touchDelegateInfo = new TouchDelegateInfo(
+                        targetMap, false);
+                return touchDelegateInfo;
+            }
+
+            @Override
+            public TouchDelegateInfo[] newArray(int size) {
+                return new TouchDelegateInfo[size];
+            }
+        };
+    }
+
+    /**
      * @see android.os.Parcelable.Creator
      */
     public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 08ed9d1..ca2ccaf 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -48,7 +48,6 @@
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.SparseArray;
-import android.view.Display;
 import android.view.InputChannel;
 import android.view.InputEvent;
 import android.view.InputEventSender;
@@ -266,7 +265,7 @@
      * @hide
      */
     public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
-        forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
+        getInstanceInternal();
     }
 
     private static final Object sLock = new Object();
@@ -280,17 +279,6 @@
     static InputMethodManager sInstance;
 
     /**
-     * Global map between display to {@link InputMethodManager}.
-     *
-     * <p>Currently this map works like a so-called leaky singleton.  Once an instance is registered
-     * for the associated display ID, that instance will never be garbage collected.</p>
-     *
-     * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
-     */
-    @GuardedBy("sLock")
-    private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
-
-    /**
      * @hide Flag for IInputMethodManager.windowGainedFocus: a view in
      * the window has input focus.
      */
@@ -347,8 +335,6 @@
     // Our generic input connection if the current target does not have its own.
     final IInputContext mIInputContext;
 
-    private final int mDisplayId;
-
     /**
      * True if this input method client is active, initially false.
      */
@@ -466,29 +452,6 @@
         return afm != null && afm.isAutofillUiShowing();
     }
 
-    /**
-     * Checks the consistency between {@link InputMethodManager} state and {@link View} state.
-     *
-     * @param view {@link View} to be checked
-     * @return {@code true} if {@code view} is not {@code null} and there is a {@link Context}
-     *         mismatch between {@link InputMethodManager} and {@code view}
-     */
-    private boolean shouldDispatchToViewContext(@Nullable View view) {
-        if (view == null) {
-            return false;
-        }
-        final int viewDisplayId = getDisplayId(view.getContext());
-        if (viewDisplayId != mDisplayId) {
-            Log.w(TAG, "b/117267690: Context mismatch found. view=" + view + " belongs to"
-                    + " displayId=" + viewDisplayId
-                    + " but InputMethodManager belongs to displayId=" + mDisplayId
-                    + ". Use the right InputMethodManager instance to avoid performance overhead.",
-                    new Throwable());
-            return true;
-        }
-        return false;
-    }
-
     private static boolean canStartInput(View servedView) {
         // We can start input ether the servedView has window focus
         // or the activity is showing autofill ui.
@@ -770,57 +733,33 @@
                 });
     }
 
-    InputMethodManager(int displayId, Looper looper) throws ServiceNotFoundException {
+    InputMethodManager(Looper looper) throws ServiceNotFoundException {
         mService = getIInputMethodManager();
         mMainLooper = looper;
         mH = new H(looper);
-        mDisplayId = displayId;
         mIInputContext = new ControlledInputConnectionWrapper(looper,
                 mDummyInputConnection, this);
     }
 
-    private static int getDisplayId(Context context) {
-        final Display display = context.getDisplay();
-        return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY;
-    }
-
     /**
-     * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
+     * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already
+     * exist.
      *
-     * @param context {@link Context} for which IME APIs need to work
-     * @return {@link InputMethodManager} instance
+     * @return global {@link InputMethodManager} instance
      * @hide
      */
-    @Nullable
-    public static InputMethodManager forContext(Context context) {
-        final int displayId = getDisplayId(context);
-        // For better backward compatibility, we always use Looper.getMainLooper() for the default
-        // display case.
-        final Looper looper = displayId == Display.DEFAULT_DISPLAY
-                ? Looper.getMainLooper() : context.getMainLooper();
-        return forContextInternal(displayId, looper);
-    }
-
-    @Nullable
-    private static InputMethodManager forContextInternal(int displayId, Looper looper) {
-        final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
+    public static InputMethodManager getInstanceInternal() {
         synchronized (sLock) {
-            InputMethodManager instance = sInstanceMap.get(displayId);
-            if (instance != null) {
-                return instance;
+            if (sInstance == null) {
+                try {
+                    final InputMethodManager imm = new InputMethodManager(Looper.getMainLooper());
+                    imm.mService.addClient(imm.mClient, imm.mIInputContext);
+                    sInstance = imm;
+                } catch (ServiceNotFoundException | RemoteException e) {
+                    throw new IllegalStateException(e);
+                }
             }
-            try {
-                instance = new InputMethodManager(displayId, looper);
-                instance.mService.addClient(instance.mClient, instance.mIInputContext, displayId);
-            } catch (ServiceNotFoundException | RemoteException e) {
-                throw new IllegalStateException(e);
-            }
-            // For backward compatibility, store the instance also to sInstance for default display.
-            if (sInstance == null && isDefaultDisplay) {
-                sInstance = instance;
-            }
-            sInstanceMap.put(displayId, instance);
-            return instance;
+            return sInstance;
         }
     }
 
@@ -977,11 +916,6 @@
      * input method.
      */
     public boolean isActive(View view) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class).isActive(view);
-        }
-
         checkFocus();
         synchronized (mH) {
             return (mServedView == view
@@ -1072,13 +1006,6 @@
     }
 
     public void displayCompletions(View view, CompletionInfo[] completions) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .displayCompletions(view, completions);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if (mServedView != view && (mServedView == null
@@ -1097,13 +1024,6 @@
     }
 
     public void updateExtractedText(View view, int token, ExtractedText text) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateExtractedText(view, token, text);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if (mServedView != view && (mServedView == null
@@ -1145,12 +1065,6 @@
      * 0 or have the {@link #SHOW_IMPLICIT} bit set.
      */
     public boolean showSoftInput(View view, int flags) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class)
-                    .showSoftInput(view, flags);
-        }
-
         return showSoftInput(view, flags, null);
     }
 
@@ -1213,12 +1127,6 @@
      * {@link #RESULT_HIDDEN}.
      */
     public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class)
-                    .showSoftInput(view, flags, resultReceiver);
-        }
-
         checkFocus();
         synchronized (mH) {
             if (mServedView != view && (mServedView == null
@@ -1382,12 +1290,6 @@
      * @param view The view whose text has changed.
      */
     public void restartInput(View view) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class).restartInput(view);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if (mServedView != view && (mServedView == null
@@ -1812,13 +1714,6 @@
      */
     public void updateSelection(View view, int selStart, int selEnd,
             int candidatesStart, int candidatesEnd) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if ((mServedView != view && (mServedView == null
@@ -1856,12 +1751,6 @@
      * Notify the event when the user tapped or clicked the text view.
      */
     public void viewClicked(View view) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class).viewClicked(view);
-            return;
-        }
-
         final boolean focusChanged = mServedView != mNextServedView;
         checkFocus();
         synchronized (mH) {
@@ -1926,13 +1815,6 @@
      */
     @Deprecated
     public void updateCursor(View view, int left, int top, int right, int bottom) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateCursor(view, left, top, right, bottom);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if ((mServedView != view && (mServedView == null
@@ -1964,13 +1846,6 @@
         if (view == null || cursorAnchorInfo == null) {
             return;
         }
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateCursorAnchorInfo(view, cursorAnchorInfo);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if ((mServedView != view &&
@@ -2016,13 +1891,6 @@
      * @param data Any data to include with the command.
      */
     public void sendAppPrivateCommand(View view, String action, Bundle data) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .sendAppPrivateCommand(view, action, data);
-            return;
-        }
-
         checkFocus();
         synchronized (mH) {
             if ((mServedView != view && (mServedView == null
@@ -2194,13 +2062,6 @@
      */
     public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
             @NonNull KeyEvent event) {
-        // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(targetView)) {
-            targetView.getContext().getSystemService(InputMethodManager.class)
-                    .dispatchKeyEventFromInputMethod(targetView, event);
-            return;
-        }
-
         synchronized (mH) {
             ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
             if (viewRootImpl == null) {
@@ -2690,7 +2551,6 @@
         sb.append(",windowFocus=" + view.hasWindowFocus());
         sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
         sb.append(",window=" + view.getWindowToken());
-        sb.append(",displayId=" + getDisplayId(view.getContext()));
         sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
         return sb.toString();
     }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 35ff6cc..8f17e96 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -42,6 +42,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.graphics.drawable.RippleDrawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -152,6 +153,7 @@
     private static final int SET_REMOTE_INPUTS_ACTION_TAG = 18;
     private static final int LAYOUT_PARAM_ACTION_TAG = 19;
     private static final int OVERRIDE_TEXT_COLORS_TAG = 20;
+    private static final int SET_RIPPLE_DRAWABLE_COLOR_TAG = 21;
 
     /**
      * Application that hosts the remote views.
@@ -1122,6 +1124,53 @@
         PorterDuff.Mode filterMode;
     }
 
+    /**
+     * Equivalent to calling
+     * {@link RippleDrawable#setColor(ColorStateList)},
+     * on the {@link Drawable} of a given view.
+     * <p>
+     * The operation will be performed on the {@link Drawable} returned by the
+     * target {@link View#getBackground()}.
+     * <p>
+     */
+    private class SetRippleDrawableColor extends Action {
+
+        ColorStateList mColorStateList;
+
+        SetRippleDrawableColor(int id, ColorStateList colorStateList) {
+            this.viewId = id;
+            this.mColorStateList = colorStateList;
+        }
+
+        SetRippleDrawableColor(Parcel parcel) {
+            viewId = parcel.readInt();
+            mColorStateList = parcel.readParcelable(null);
+        }
+
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(viewId);
+            dest.writeParcelable(mColorStateList, 0);
+        }
+
+        @Override
+        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+            final View target = root.findViewById(viewId);
+            if (target == null) return;
+
+            // Pick the correct drawable to modify for this view
+            Drawable targetDrawable = target.getBackground();
+
+            if (targetDrawable instanceof RippleDrawable) {
+                ((RippleDrawable) targetDrawable.mutate()).setColor(mColorStateList);
+            }
+        }
+
+        @Override
+        public int getActionTag() {
+            return SET_RIPPLE_DRAWABLE_COLOR_TAG;
+        }
+    }
+
     private final class ViewContentNavigation extends Action {
         final boolean mNext;
 
@@ -2394,6 +2443,8 @@
                 return new LayoutParamAction(parcel);
             case OVERRIDE_TEXT_COLORS_TAG:
                 return new OverrideTextColorsAction(parcel);
+            case SET_RIPPLE_DRAWABLE_COLOR_TAG:
+                return new SetRippleDrawableColor(parcel);
             default:
                 throw new ActionException("Tag " + tag + " not found");
         }
@@ -2855,6 +2906,22 @@
 
     /**
      * @hide
+     * Equivalent to calling
+     * {@link RippleDrawable#setColor(ColorStateList)} on the {@link Drawable} of a given view,
+     * assuming it's a {@link RippleDrawable}.
+     * <p>
+     *
+     * @param viewId The id of the view that contains the target
+     *            {@link RippleDrawable}
+     * @param colorStateList Specify a color for a
+     *            {@link ColorStateList} for this drawable.
+     */
+    public void setRippleDrawableColor(int viewId, ColorStateList colorStateList) {
+        addAction(new SetRippleDrawableColor(viewId, colorStateList));
+    }
+
+    /**
+     * @hide
      * Equivalent to calling {@link android.widget.ProgressBar#setProgressTintList}.
      *
      * @param viewId The id of the view whose tint should change
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9d06680..f74c234 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3521,7 +3521,7 @@
         Typeface mFontTypeface = null;
         boolean mFontFamilyExplicit = false;
         int mTypefaceIndex = -1;
-        int mStyleIndex = -1;
+        int mTextStyle = 0;
         int mFontWeight = -1;
         boolean mAllCaps = false;
         int mShadowColor = 0;
@@ -3547,7 +3547,7 @@
                     + "    mFontTypeface:" + mFontTypeface + "\n"
                     + "    mFontFamilyExplicit:" + mFontFamilyExplicit + "\n"
                     + "    mTypefaceIndex:" + mTypefaceIndex + "\n"
-                    + "    mStyleIndex:" + mStyleIndex + "\n"
+                    + "    mTextStyle:" + mTextStyle + "\n"
                     + "    mFontWeight:" + mFontWeight + "\n"
                     + "    mAllCaps:" + mAllCaps + "\n"
                     + "    mShadowColor:" + mShadowColor + "\n"
@@ -3672,7 +3672,7 @@
                     attributes.mFontFamilyExplicit = true;
                     break;
                 case com.android.internal.R.styleable.TextAppearance_textStyle:
-                    attributes.mStyleIndex = appearance.getInt(attr, attributes.mStyleIndex);
+                    attributes.mTextStyle = appearance.getInt(attr, attributes.mTextStyle);
                     break;
                 case com.android.internal.R.styleable.TextAppearance_textFontWeight:
                     attributes.mFontWeight = appearance.getInt(attr, attributes.mFontWeight);
@@ -3742,7 +3742,7 @@
             attributes.mFontFamily = null;
         }
         setTypefaceFromAttrs(attributes.mFontTypeface, attributes.mFontFamily,
-                attributes.mTypefaceIndex, attributes.mStyleIndex, attributes.mFontWeight);
+                attributes.mTypefaceIndex, attributes.mTextStyle, attributes.mFontWeight);
 
         if (attributes.mShadowColor != 0) {
             setShadowLayer(attributes.mShadowRadius, attributes.mShadowDx, attributes.mShadowDy,
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index a8edfb6..498de53 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -16,12 +16,17 @@
 
 package com.android.internal.app;
 
+import static android.content.res.ResourceId.ID_NULL;
+
 import android.Manifest;
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.SuspendDialogInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Slog;
@@ -31,16 +36,19 @@
 
 public class SuspendedAppActivity extends AlertActivity
         implements DialogInterface.OnClickListener {
-    private static final String TAG = "SuspendedAppActivity";
-    public static final String EXTRA_SUSPENDED_PACKAGE =
-            "SuspendedAppActivity.extra.SUSPENDED_PACKAGE";
+    private static final String TAG = SuspendedAppActivity.class.getSimpleName();
+    private static final String PACKAGE_NAME = "com.android.internal.app";
+
+    public static final String EXTRA_SUSPENDED_PACKAGE = PACKAGE_NAME + ".extra.SUSPENDED_PACKAGE";
     public static final String EXTRA_SUSPENDING_PACKAGE =
-            "SuspendedAppActivity.extra.SUSPENDING_PACKAGE";
-    public static final String EXTRA_DIALOG_MESSAGE = "SuspendedAppActivity.extra.DIALOG_MESSAGE";
+            PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
+    public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
 
     private Intent mMoreDetailsIntent;
     private int mUserId;
     private PackageManager mPm;
+    private Resources mSuspendingAppResources;
+    private SuspendDialogInfo mSuppliedDialogInfo;
 
     private CharSequence getAppLabel(String packageName) {
         try {
@@ -66,6 +74,65 @@
         return null;
     }
 
+    private Drawable resolveIcon() {
+        final int iconId = (mSuppliedDialogInfo != null) ? mSuppliedDialogInfo.getIconResId()
+                : ID_NULL;
+        if (iconId != ID_NULL && mSuspendingAppResources != null) {
+            try {
+                return mSuspendingAppResources.getDrawable(iconId, null);
+            } catch (Resources.NotFoundException nfe) {
+                Slog.e(TAG, "Could not resolve drawable resource id " + iconId);
+            }
+        }
+        return null;
+    }
+
+    private String resolveTitle() {
+        final int titleId = (mSuppliedDialogInfo != null) ? mSuppliedDialogInfo.getTitleResId()
+                : ID_NULL;
+        if (titleId != ID_NULL && mSuspendingAppResources != null) {
+            try {
+                return mSuspendingAppResources.getString(titleId);
+            } catch (Resources.NotFoundException nfe) {
+                Slog.e(TAG, "Could not resolve string resource id " + titleId);
+            }
+        }
+        return getString(R.string.app_suspended_title);
+    }
+
+    private String resolveDialogMessage(String suspendingPkg, String suspendedPkg) {
+        final CharSequence suspendedAppLabel = getAppLabel(suspendedPkg);
+        if (mSuppliedDialogInfo != null) {
+            final int messageId = mSuppliedDialogInfo.getDialogMessageResId();
+            final String message = mSuppliedDialogInfo.getDialogMessage();
+            if (messageId != ID_NULL && mSuspendingAppResources != null) {
+                try {
+                    return mSuspendingAppResources.getString(messageId, suspendedAppLabel);
+                } catch (Resources.NotFoundException nfe) {
+                    Slog.e(TAG, "Could not resolve string resource id " + messageId);
+                }
+            } else if (message != null) {
+                return String.format(getResources().getConfiguration().getLocales().get(0), message,
+                        suspendedAppLabel);
+            }
+        }
+        return getString(R.string.app_suspended_default_message, suspendedAppLabel,
+                getAppLabel(suspendingPkg));
+    }
+
+    private String resolveNeutralButtonText() {
+        final int buttonTextId = (mSuppliedDialogInfo != null)
+                ? mSuppliedDialogInfo.getNeutralButtonTextResId() : ID_NULL;
+        if (buttonTextId != ID_NULL && mSuspendingAppResources != null) {
+            try {
+                return mSuspendingAppResources.getString(buttonTextId);
+            } catch (Resources.NotFoundException nfe) {
+                Slog.e(TAG, "Could not resolve string resource id " + buttonTextId);
+            }
+        }
+        return getString(R.string.app_suspended_more_details);
+    }
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -79,26 +146,26 @@
             finish();
             return;
         }
-        final String suppliedMessage = intent.getStringExtra(EXTRA_DIALOG_MESSAGE);
         final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
         final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
-        final CharSequence suspendedAppLabel = getAppLabel(suspendedPackage);
-        final CharSequence dialogMessage;
-        if (suppliedMessage == null) {
-            dialogMessage = getString(R.string.app_suspended_default_message, suspendedAppLabel,
-                    getAppLabel(suspendingPackage));
-        } else {
-            dialogMessage = String.format(getResources().getConfiguration().getLocales().get(0),
-                    suppliedMessage, suspendedAppLabel);
+        mSuppliedDialogInfo = intent.getParcelableExtra(EXTRA_DIALOG_INFO);
+        if (mSuppliedDialogInfo != null) {
+            try {
+                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(suspendingPackage,
+                        mUserId);
+            } catch (PackageManager.NameNotFoundException ne) {
+                Slog.e(TAG, "Could not find resources for " + suspendingPackage, ne);
+            }
         }
 
         final AlertController.AlertParams ap = mAlertParams;
-        ap.mTitle = getString(R.string.app_suspended_title);
-        ap.mMessage = dialogMessage;
+        ap.mIcon = resolveIcon();
+        ap.mTitle = resolveTitle();
+        ap.mMessage = resolveDialogMessage(suspendingPackage, suspendedPackage);
         ap.mPositiveButtonText = getString(android.R.string.ok);
         mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
         if (mMoreDetailsIntent != null) {
-            ap.mNeutralButtonText = getString(R.string.app_suspended_more_details);
+            ap.mNeutralButtonText = resolveNeutralButtonText();
         }
         ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
         setupAlert();
@@ -116,11 +183,11 @@
     }
 
     public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
-            String suspendingPackage, String dialogMessage, int userId) {
+            String suspendingPackage, SuspendDialogInfo dialogInfo, int userId) {
         return new Intent()
                 .setClassName("android", SuspendedAppActivity.class.getName())
                 .putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
-                .putExtra(EXTRA_DIALOG_MESSAGE, dialogMessage)
+                .putExtra(EXTRA_DIALOG_INFO, dialogInfo)
                 .putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
                 .putExtra(Intent.EXTRA_USER_ID, userId)
                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 33b9ff7..017da55 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5330,6 +5330,7 @@
                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
                         + Integer.toHexString(mHistoryCur.states));
                 mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
+                StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
             }
         }
 
@@ -5341,6 +5342,7 @@
                         + Integer.toHexString(mHistoryCur.states));
                 newHistory = true;
                 mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
+                StatsLog.write(StatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin);
             }
         }
 
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index e4724ff..8dc97fe 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -66,6 +66,7 @@
             session = session == null ? new DispatchSession() : session;
             session.startTimeMicro = getElapsedRealtimeMicro();
             session.cpuStartMicro = getThreadTimeMicro();
+            session.systemUptimeMillis = getSystemUptimeMillis();
             return session;
         }
 
@@ -85,12 +86,18 @@
                 entry.messageCount++;
                 if (session != DispatchSession.NOT_SAMPLED) {
                     entry.recordedMessageCount++;
-                    long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
-                    long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
+                    final long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
+                    final long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
                     entry.totalLatencyMicro += latency;
                     entry.maxLatencyMicro = Math.max(entry.maxLatencyMicro, latency);
                     entry.cpuUsageMicro += cpuUsage;
                     entry.maxCpuUsageMicro = Math.max(entry.maxCpuUsageMicro, cpuUsage);
+                    if (msg.getWhen() > 0) {
+                        final long delay = Math.max(0L, session.systemUptimeMillis - msg.getWhen());
+                        entry.delayMillis += delay;
+                        entry.maxDelayMillis = Math.max(entry.maxDelayMillis, delay);
+                        entry.recordedDelayMessageCount++;
+                    }
                 }
             }
         }
@@ -206,6 +213,10 @@
         return SystemClock.elapsedRealtimeNanos() / 1000;
     }
 
+    protected long getSystemUptimeMillis() {
+        return SystemClock.uptimeMillis();
+    }
+
     protected boolean shouldCollectDetailedData() {
         return ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
     }
@@ -214,6 +225,7 @@
         static final DispatchSession NOT_SAMPLED = new DispatchSession();
         public long startTimeMicro;
         public long cpuStartMicro;
+        public long systemUptimeMillis;
     }
 
     private static class Entry {
@@ -228,6 +240,9 @@
         public long maxLatencyMicro;
         public long cpuUsageMicro;
         public long maxCpuUsageMicro;
+        public long recordedDelayMessageCount;
+        public long delayMillis;
+        public long maxDelayMillis;
 
         Entry(Message msg, boolean isInteractive) {
             this.workSourceUid = msg.workSourceUid;
@@ -251,6 +266,9 @@
             maxLatencyMicro = 0;
             cpuUsageMicro = 0;
             maxCpuUsageMicro = 0;
+            delayMillis = 0;
+            maxDelayMillis = 0;
+            recordedDelayMessageCount = 0;
         }
 
         static int idFor(Message msg, boolean isInteractive) {
@@ -281,6 +299,9 @@
         public final long maxLatencyMicros;
         public final long cpuUsageMicros;
         public final long maxCpuUsageMicros;
+        public final long maxDelayMillis;
+        public final long delayMillis;
+        public final long recordedDelayMessageCount;
 
         ExportedEntry(Entry entry) {
             this.workSourceUid = entry.workSourceUid;
@@ -301,6 +322,9 @@
             this.maxLatencyMicros = entry.maxLatencyMicro;
             this.cpuUsageMicros = entry.cpuUsageMicro;
             this.maxCpuUsageMicros = entry.maxCpuUsageMicro;
+            this.delayMillis = entry.delayMillis;
+            this.maxDelayMillis = entry.maxDelayMillis;
+            this.recordedDelayMessageCount = entry.recordedDelayMessageCount;
         }
     }
 }
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index bf31c7d..1ee4269 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -29,7 +29,6 @@
 import com.android.internal.util.FastPrintWriter;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index dceacda..5f1243f 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -31,8 +31,7 @@
  * applications.
  */
 interface IInputMethodManager {
-    void addClient(in IInputMethodClient client, in IInputContext inputContext,
-            int untrustedDisplayId);
+    void addClient(in IInputMethodClient client, in IInputContext inputContext);
 
     // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getInputMethodList();
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index ec8e8da..101fd41 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -51,9 +51,6 @@
             ResultCode.ERROR_INVALID_USER,
             ResultCode.ERROR_NULL_EDITOR_INFO,
             ResultCode.ERROR_NOT_IME_TARGET_WINDOW,
-            ResultCode.ERROR_NO_EDITOR,
-            ResultCode.ERROR_DISPLAY_ID_MISMATCH,
-            ResultCode.ERROR_INVALID_DISPLAY_ID,
     })
     public @interface ResultCode {
         /**
@@ -142,22 +139,13 @@
          * The client should try to restart input when its {@link android.view.Window} is focused
          * again.</p>
          *
-         * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int, int)
+         * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int)
          */
         int ERROR_NOT_IME_TARGET_WINDOW = 11;
         /**
          * Indicates that focused view in the current window is not an editor.
          */
         int ERROR_NO_EDITOR = 12;
-        /**
-         * Indicates that there is a mismatch in display ID between IME client and focused Window.
-         */
-        int ERROR_DISPLAY_ID_MISMATCH = 13;
-        /**
-         * Indicates that current IME client is no longer allowed to access to the associated
-         * display.
-         */
-        int ERROR_INVALID_DISPLAY_ID = 14;
     }
 
     @ResultCode
@@ -283,10 +271,6 @@
                 return "ERROR_NULL_EDITOR_INFO";
             case ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
                 return "ERROR_NOT_IME_TARGET_WINDOW";
-            case ResultCode.ERROR_DISPLAY_ID_MISMATCH:
-                return "ERROR_DISPLAY_ID_MISMATCH";
-            case ResultCode.ERROR_INVALID_DISPLAY_ID:
-                return "ERROR_INVALID_DISPLAY_ID";
             default:
                 return "Unknown(" + result + ")";
         }
@@ -332,15 +316,4 @@
      */
     public static final InputBindResult INVALID_USER = error(ResultCode.ERROR_INVALID_USER);
 
-    /**
-     * Predefined error object for {@link ResultCode#ERROR_DISPLAY_ID_MISMATCH}.
-     */
-    public static final InputBindResult DISPLAY_ID_MISMATCH =
-            error(ResultCode.ERROR_DISPLAY_ID_MISMATCH);
-
-    /**
-     * Predefined error object for {@link ResultCode#ERROR_INVALID_DISPLAY_ID}.
-     */
-    public static final InputBindResult INVALID_DISPLAY_ID =
-            error(ResultCode.ERROR_INVALID_DISPLAY_ID);
 }
diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java
index 9bf0948..7a01749 100644
--- a/core/java/com/android/internal/widget/AlertDialogLayout.java
+++ b/core/java/com/android/internal/widget/AlertDialogLayout.java
@@ -18,6 +18,7 @@
 
 import android.annotation.AttrRes;
 import android.annotation.Nullable;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.StyleRes;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -50,6 +51,7 @@
         super(context);
     }
 
+    @UnsupportedAppUsage
     public AlertDialogLayout(@Nullable Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
     }
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index ab8be33..0ca6743 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -40,6 +41,7 @@
 
     private int mMinimumHeight = 0;
 
+    @UnsupportedAppUsage
     public ButtonBarLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
 
diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java
index 7ea3d6b..405436c 100644
--- a/core/java/com/android/internal/widget/DialogTitle.java
+++ b/core/java/com/android/internal/widget/DialogTitle.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.text.Layout;
@@ -37,6 +38,7 @@
         super(context, attrs, defStyleAttr);
     }
 
+    @UnsupportedAppUsage
     public DialogTitle(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 0a787b9..d68e8f8 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -331,13 +331,11 @@
         readPermissions(Environment.buildPath(
                 Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
 
-        // Allow Product to customize system configs around libs, features, permissions and apps
-        int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
-                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+        // Allow Product to customize all system configs
         readPermissions(Environment.buildPath(
-                Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
+                Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
         readPermissions(Environment.buildPath(
-                Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+                Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
 
         // Allow /product_services to customize system configs around libs, features, permissions
         // and apps.
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index c2ca2fc..ed6445d 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -84,8 +84,6 @@
         "android_view_VelocityTracker.cpp",
         "android_text_AndroidCharacter.cpp",
         "android_text_Hyphenator.cpp",
-        "android_text_LineBreaker.cpp",
-        "android_text_MeasuredParagraph.cpp",
         "android_os_Debug.cpp",
         "android_os_GraphicsEnvironment.cpp",
         "android_os_HidlSupport.cpp",
@@ -161,6 +159,8 @@
         "android/graphics/pdf/PdfEditor.cpp",
         "android/graphics/pdf/PdfRenderer.cpp",
         "android/graphics/pdf/PdfUtils.cpp",
+        "android/graphics/text/LineBreaker.cpp",
+        "android/graphics/text/MeasuredText.cpp",
         "android_media_AudioRecord.cpp",
         "android_media_AudioSystem.cpp",
         "android_media_AudioTrack.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6b55ed6..c05bad2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -145,6 +145,8 @@
 extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
 extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
+extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
+extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_DisplayListCanvas(JNIEnv* env);
 extern int register_android_view_TextureLayer(JNIEnv* env);
@@ -185,8 +187,6 @@
 extern int register_android_net_NetworkUtils(JNIEnv* env);
 extern int register_android_text_AndroidCharacter(JNIEnv *env);
 extern int register_android_text_Hyphenator(JNIEnv *env);
-extern int register_android_text_MeasuredParagraph(JNIEnv* env);
-extern int register_android_text_LineBreaker(JNIEnv *env);
 extern int register_android_opengl_classes(JNIEnv *env);
 extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
 extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
@@ -1336,8 +1336,6 @@
     REG_JNI(register_android_content_res_ApkAssets),
     REG_JNI(register_android_text_AndroidCharacter),
     REG_JNI(register_android_text_Hyphenator),
-    REG_JNI(register_android_text_MeasuredParagraph),
-    REG_JNI(register_android_text_LineBreaker),
     REG_JNI(register_android_view_InputDevice),
     REG_JNI(register_android_view_KeyCharacterMap),
     REG_JNI(register_android_os_Process),
@@ -1415,6 +1413,8 @@
     REG_JNI(register_android_graphics_pdf_PdfDocument),
     REG_JNI(register_android_graphics_pdf_PdfEditor),
     REG_JNI(register_android_graphics_pdf_PdfRenderer),
+    REG_JNI(register_android_graphics_text_MeasuredText),
+    REG_JNI(register_android_graphics_text_LineBreaker),
 
     REG_JNI(register_android_database_CursorWindow),
     REG_JNI(register_android_database_SQLiteConnection),
diff --git a/core/jni/android_text_LineBreaker.cpp b/core/jni/android/graphics/text/LineBreaker.cpp
similarity index 96%
rename from core/jni/android_text_LineBreaker.cpp
rename to core/jni/android/graphics/text/LineBreaker.cpp
index 5439107..e1f2f2b 100644
--- a/core/jni/android_text_LineBreaker.cpp
+++ b/core/jni/android/graphics/text/LineBreaker.cpp
@@ -168,8 +168,9 @@
     {"nGetReleaseResultFunc", "()J", (void*)nGetReleaseResultFunc},
 };
 
-int register_android_text_LineBreaker(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/text/NativeLineBreaker", gMethods, NELEM(gMethods));
+int register_android_graphics_text_LineBreaker(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/graphics/text/LineBreaker", gMethods,
+                                NELEM(gMethods));
 }
 
 }
diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android/graphics/text/MeasuredText.cpp
similarity index 91%
rename from core/jni/android_text_MeasuredParagraph.cpp
rename to core/jni/android/graphics/text/MeasuredText.cpp
index 18f509c..0bfadb4 100644
--- a/core/jni/android_text_MeasuredParagraph.cpp
+++ b/core/jni/android/graphics/text/MeasuredText.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "MeasuredParagraph"
+#define LOG_TAG "MeasuredText"
 
 #include "GraphicsJNI.h"
 #include "unicode/locid.h"
@@ -83,7 +83,7 @@
 }
 
 // Regular JNI
-static jlong nBuildNativeMeasuredParagraph(JNIEnv* env, jclass /* unused */, jlong builderPtr,
+static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr,
                                       jcharArray javaText, jboolean computeHyphenation,
                                       jboolean computeLayout) {
     ScopedCharArrayRO text(env, javaText);
@@ -147,7 +147,7 @@
     {"nInitBuilder", "()J", (void*) nInitBuilder},
     {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
     {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
-    {"nBuildNativeMeasuredParagraph", "(J[CZZ)J", (void*) nBuildNativeMeasuredParagraph},
+    {"nBuildMeasuredText", "(J[CZZ)J", (void*) nBuildMeasuredText},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
 };
 
@@ -160,10 +160,10 @@
     {"nGetCharWidthAt", "(JI)F", (void*) nGetCharWidthAt},  // Critical Native
 };
 
-int register_android_text_MeasuredParagraph(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph",
+int register_android_graphics_text_MeasuredText(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/graphics/text/MeasuredText",
             gMTMethods, NELEM(gMTMethods))
-        + RegisterMethodsOrDie(env, "android/text/NativeMeasuredParagraph$Builder",
+        + RegisterMethodsOrDie(env, "android/graphics/text/MeasuredText$Builder",
             gMTBuilderMethods, NELEM(gMTBuilderMethods));
 }
 
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 92235ad..b70485d 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -23,10 +23,6 @@
 
 namespace {
 
-int getCanLoadSystemLibraries_native() {
-    return android::GraphicsEnv::getInstance().getCanLoadSystemLibraries();
-}
-
 void setDriverPath(JNIEnv* env, jobject clazz, jstring path) {
     ScopedUtfChars pathChars(env, path);
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
@@ -55,7 +51,6 @@
 }
 
 const JNINativeMethod g_methods[] = {
-    { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
     { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index ecad6c0..d023d22 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -23,6 +23,7 @@
 #include <atomic>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <mutex>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -69,6 +70,7 @@
     // Class state.
     jclass mClass;
     jmethodID mExecTransact;
+    jmethodID mGetInterfaceDescriptor;
 
     // Object state.
     jfieldID mObject;
@@ -326,8 +328,32 @@
         env->DeleteGlobalRef(mObject);
     }
 
-    virtual status_t onTransact(
-        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
+    const String16& getInterfaceDescriptor() const override
+    {
+        call_once(mPopulateDescriptor, [this] {
+            JNIEnv* env = javavm_to_jnienv(mVM);
+
+            ALOGV("getInterfaceDescriptor() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
+
+            jstring descriptor = (jstring)env->CallObjectMethod(mObject, gBinderOffsets.mGetInterfaceDescriptor);
+
+            if (descriptor == nullptr) {
+                return;
+            }
+
+            static_assert(sizeof(jchar) == sizeof(char16_t), "");
+            const jchar* descriptorChars = env->GetStringChars(descriptor, nullptr);
+            const char16_t* rawDescriptor = reinterpret_cast<const char16_t*>(descriptorChars);
+            jsize rawDescriptorLen = env->GetStringLength(descriptor);
+            mDescriptor = String16(rawDescriptor, rawDescriptorLen);
+            env->ReleaseStringChars(descriptor, descriptorChars);
+        });
+
+        return mDescriptor;
+    }
+
+    status_t onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override
     {
         JNIEnv* env = javavm_to_jnienv(mVM);
 
@@ -376,7 +402,7 @@
         return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
     }
 
-    virtual status_t dump(int fd, const Vector<String16>& args)
+    status_t dump(int fd, const Vector<String16>& args) override
     {
         return 0;
     }
@@ -384,6 +410,9 @@
 private:
     JavaVM* const   mVM;
     jobject const   mObject;  // GlobalRef to Java Binder
+
+    mutable std::once_flag mPopulateDescriptor;
+    mutable String16 mDescriptor;
 };
 
 // ----------------------------------------------------------------------------
@@ -926,6 +955,8 @@
 
     gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
     gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
+    gBinderOffsets.mGetInterfaceDescriptor = GetMethodIDOrDie(env, clazz, "getInterfaceDescriptor",
+        "()Ljava/lang/String;");
     gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
 
     return RegisterMethodsOrDie(
diff --git a/core/proto/android/internal/powerprofile.proto b/core/proto/android/internal/powerprofile.proto
index 9dd5e7e..b0c8b56 100644
--- a/core/proto/android/internal/powerprofile.proto
+++ b/core/proto/android/internal/powerprofile.proto
@@ -35,7 +35,7 @@
         repeated double core_power = 5;
     }
 
-    repeated CpuCluster cpu_cluster = 41;
+    repeated CpuCluster cpu_cluster = 40;
 
     optional double wifi_scan = 4;
 
@@ -85,27 +85,27 @@
 
     optional double ambient_display = 27;
 
-    optional double screen_on = 29;
+    optional double screen_on = 28;
 
-    optional double radio_on = 30;
+    optional double radio_on = 29;
 
-    optional double radio_scanning = 31;
+    optional double radio_scanning = 30;
 
-    optional double radio_active = 32;
+    optional double radio_active = 31;
 
-    optional double screen_full = 33;
+    optional double screen_full = 32;
 
-    optional double audio = 34;
+    optional double audio = 33;
 
-    optional double video = 35;
+    optional double video = 34;
 
-    optional double flashlight = 36;
+    optional double flashlight = 35;
 
-    optional double memory = 37;
+    optional double memory = 36;
 
-    optional double camera = 38;
+    optional double camera = 37;
 
-    optional double wifi_batched_scan = 39;
+    optional double wifi_batched_scan = 38;
 
-    optional double battery_capacity = 40;
+    optional double battery_capacity = 39;
 }
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 47dbc07..a02602e 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -397,10 +397,9 @@
         // Ordered GPU debug layer list
         // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
         // App will load ANGLE instead of native GLES drivers.
         optional SettingProto angle_enabled_app = 3;
-        // App that can provide layer libraries.
-        optional SettingProto debug_layer_app = 4;
     }
     optional Gpu gpu = 59;
 
diff --git a/proto/src/stats_enums.proto b/core/proto/android/stats/enums.proto
similarity index 91%
rename from proto/src/stats_enums.proto
rename to core/proto/android/stats/enums.proto
index 6c892cf..2320a01 100644
--- a/proto/src/stats_enums.proto
+++ b/core/proto/android/stats/enums.proto
@@ -16,8 +16,7 @@
 
 syntax = "proto2";
 
-package android.os.statsd;
-option java_package = "com.android.os";
+package android.stats;
 option java_outer_classname = "StatsEnums";
 
 enum EventType {
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index 32975a5..fba2e51 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -61,3 +61,64 @@
     SIGNAL_STRENGTH_GOOD = 3;
     SIGNAL_STRENGTH_GREAT = 4;
 }
+
+
+enum ServiceStateEnum {
+    /**
+     * Normal operation condition, the phone is registered
+     * with an operator either in home network or in roaming.
+     */
+    SERVICE_STATE_IN_SERVICE = 0;
+
+    /**
+     * Phone is not registered with any operator, the phone
+     * can be currently searching a new operator to register to, or not
+     * searching to registration at all, or registration is denied, or radio
+     * signal is not available.
+     */
+    SERVICE_STATE_OUT_OF_SERVICE = 1;
+
+    /**
+     * The phone is registered and locked.  Only emergency numbers are allowed. {@more}
+     */
+    SERVICE_STATE_EMERGENCY_ONLY = 2;
+
+    /**
+     * Radio of telephony is explicitly powered off.
+     */
+    SERVICE_STATE_POWER_OFF = 3;
+}
+
+enum SimStateEnum {
+    SIM_STATE_UNKNOWN = 0;
+    /** SIM card state: no SIM card is available in the device */
+    SIM_STATE_ABSENT = 1;
+    /** SIM card state: Locked: requires the user's SIM PIN to unlock */
+    SIM_STATE_PIN_REQUIRED = 2;
+    /** SIM card state: Locked: requires the user's SIM PUK to unlock */
+    SIM_STATE_PUK_REQUIRED = 3;
+    /** SIM card state: Locked: requires a network PIN to unlock */
+    SIM_STATE_NETWORK_LOCKED = 4;
+    /** SIM card state: Ready */
+    SIM_STATE_READY = 5;
+    /** SIM card state: SIM Card is NOT READY */
+    SIM_STATE_NOT_READY = 6;
+    /** SIM card state: SIM Card Error, permanently disabled */
+    SIM_STATE_PERM_DISABLED = 7;
+    /** SIM card state: SIM Card Error, present but faulty */
+    SIM_STATE_CARD_IO_ERROR = 8;
+    /** SIM card state: SIM Card restricted, present but not usable due to
+     * carrier restrictions.
+     */
+    SIM_STATE_CARD_RESTRICTED = 9;
+    /**
+     * SIM card state: Loaded: SIM card applications have been loaded
+     * @hide
+     */
+    SIM_STATE_LOADED = 10;
+    /**
+     * SIM card state: SIM Card is present
+     * @hide
+     */
+    SIM_STATE_PRESENT = 11;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f3f012d..1ae5f03 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -138,7 +138,6 @@
     <protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
     <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
-    <protected-broadcast android:name="android.bluetooth.device.action.DISAPPEARED" />
     <protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
     <protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
     <protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
@@ -1151,6 +1150,28 @@
         android:protectionLevel="dangerous|instant"/>
 
     <!-- ====================================================================== -->
+    <!-- Permissions for activity recognition                        -->
+    <!-- ====================================================================== -->
+    <eat-comment />
+
+    <!-- Used for permissions that are associated with activity recognition.
+         TODO(zezeozue). STOPSHIP: Add icon -->
+    <permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
+        android:label="@string/permgrouplab_activityRecognition"
+        android:description="@string/permgroupdesc_activityRecognition"
+        android:request="@string/permgrouprequest_activityRecognition"
+        android:priority="1000" />
+
+    <!-- Allows an application to recognize physical activity.
+         <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.ACTIVITY_RECOGNITION"
+        android:permissionGroup="android.permission-group.ACTIVITY_RECOGNITION"
+        android:label="@string/permlab_activityRecognition"
+        android:description="@string/permdesc_activityRecognition"
+        android:protectionLevel="dangerous|instant" />
+
+    <!-- ====================================================================== -->
     <!-- Permissions for accessing the UCE Service                              -->
     <!-- ====================================================================== -->
 
@@ -1546,6 +1567,7 @@
 
     <!-- Allows SetupWizard to call methods in Networking services
          <p>Not for use by any other third-party or privileged applications.
+         @SystemApi
          @hide This should only be used by SetupWizard.
     -->
     <permission android:name="android.permission.NETWORK_SETUP_WIZARD"
@@ -2748,7 +2770,7 @@
         android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an application to use
-         {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
+         {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
          to hide non-system-overlay windows.
          <p>Not for use by third-party applications.
          @hide
diff --git a/core/res/res/layout/notification_material_media_action.xml b/core/res/res/layout/notification_material_media_action.xml
index 900ca2d..dd79a0b 100644
--- a/core/res/res/layout/notification_material_media_action.xml
+++ b/core/res/res/layout/notification_material_media_action.xml
@@ -18,7 +18,6 @@
 <ImageButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     style="@android:style/Widget.Material.Button.Borderless.Small"
-    android:id="@+id/action0"
     android:layout_width="@dimen/media_notification_action_button_size"
     android:layout_height="@dimen/media_notification_action_button_size"
     android:paddingBottom="8dp"
@@ -28,4 +27,5 @@
     android:layout_marginEnd="2dp"
     android:gravity="center"
     android:background="@drawable/notification_material_media_action_background"
+    android:visibility="gone"
     />
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index b4e26483..5cb93eb 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -59,7 +59,26 @@
             android:orientation="horizontal"
             android:layoutDirection="ltr"
             style="@style/NotificationMediaActionContainer" >
-            <!-- media buttons will be added here -->
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action0"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action1"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action2"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action3"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action4"
+            />
         </LinearLayout>
     </LinearLayout>
 </com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 3a0912b..01b0866 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -65,7 +65,18 @@
             android:layoutDirection="ltr"
             android:orientation="horizontal"
             >
-            <!-- media buttons will be added here -->
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action0"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action1"
+            />
+            <include
+                layout="@layout/notification_material_media_action"
+                android:id="@+id/action2"
+            />
         </LinearLayout>
     </LinearLayout>
 </FrameLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aeeba59..cb97a2a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3367,22 +3367,22 @@
     <bool name="config_sendPackageName">false</bool>
 
     <!-- Name for the set of keys associating package names -->
-    <string name="config_help_package_name_key" translatable="false"></string>
+    <string name="config_helpPackageNameKey" translatable="false"></string>
 
     <!-- Name for the set of values of package names -->
-    <string name="config_help_package_name_value" translatable="false"></string>
+    <string name="config_helpPackageNameValue" translatable="false"></string>
 
     <!-- Intent key for the package name keys -->
-    <string name="config_help_intent_extra_key" translatable="false"></string>
+    <string name="config_helpIntentExtraKey" translatable="false"></string>
 
     <!-- Intent key for package name values -->
-    <string name="config_help_intent_name_key" translatable="false"></string>
+    <string name="config_helpIntentNameKey" translatable="false"></string>
 
     <!-- Intent key for the package name keys -->
-    <string name="config_feedback_intent_extra_key" translatable="false"></string>
+    <string name="config_feedbackIntentExtraKey" translatable="false"></string>
 
     <!-- Intent key for package name values -->
-    <string name="config_feedback_intent_name_key" translatable="false"></string>
+    <string name="config_feedbackIntentNameKey" translatable="false"></string>
 
     <!-- The apps that need to be hidden when they are disabled -->
     <string-array name="config_hideWhenDisabled_packageNames"></string-array>
@@ -3487,7 +3487,7 @@
     <string name="config_headlineFontFamilyMedium">@string/font_family_button_material</string>
 
     <!-- Size of icon shown beside a preference locked by admin -->
-    <dimen name="config_restricted_icon_size">@dimen/restricted_icon_size_material</dimen>
+    <dimen name="config_restrictedIconSize">@dimen/restricted_icon_size_material</dimen>
 
     <string translatable="false" name="config_batterySaverDeviceSpecificConfig"></string>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2e42e4a..9551718 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2930,17 +2930,17 @@
 
     <public-group type="string" first-id="0x0104001b">
         <!-- @hide @SystemApi -->
-        <public name="config_help_package_name_key" />
+        <public name="config_helpPackageNameKey" />
         <!-- @hide @SystemApi -->
-        <public name="config_help_package_name_value" />
+        <public name="config_helpPackageNameValue" />
         <!-- @hide @SystemApi -->
-        <public name="config_help_intent_extra_key" />
+        <public name="config_helpIntentExtraKey" />
         <!-- @hide @SystemApi -->
-        <public name="config_help_intent_name_key" />
+        <public name="config_helpIntentNameKey" />
         <!-- @hide @SystemApi -->
-        <public name="config_feedback_intent_extra_key" />
+        <public name="config_feedbackIntentExtraKey" />
         <!-- @hide @SystemApi -->
-        <public name="config_feedback_intent_name_key" />
+        <public name="config_feedbackIntentNameKey" />
     </public-group>
 
     <public-group type="bool" first-id="0x01110000">
@@ -2950,7 +2950,7 @@
 
     <public-group type="dimen" first-id="0x01050007">
         <!-- @hide @SystemApi -->
-        <public name="config_restricted_icon_size" />
+        <public name="config_restrictedIconSize" />
     </public-group>
 
   <!-- ===============================================================
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6bf893d..fa44061 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -734,6 +734,14 @@
     <string name="permgrouprequest_microphone">Allow
         &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
 
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=40]-->
+    <string name="permgrouplab_activityRecognition">Activity recognition</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=40]-->
+    <string name="permgroupdesc_activityRecognition">recognize activity</string>
+    <!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
+    <string name="permgrouprequest_activityRecognition">Allow
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to recognize your physical activity?</string>
+
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_camera">Camera</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1151,6 +1159,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_sim_communication">Allows the app to send commands to the SIM. This is very dangerous.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50]-->
+    <string name="permlab_activityRecognition">recognize physical activity</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=120]-->
+    <string name="permdesc_activityRecognition">This app can recognize your physical activity.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_camera">take pictures and videos</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6f28b2c..09da4fc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -186,6 +186,8 @@
   <java-symbol type="id" name="action0" />
   <java-symbol type="id" name="action1" />
   <java-symbol type="id" name="action2" />
+  <java-symbol type="id" name="action3" />
+  <java-symbol type="id" name="action4" />
   <java-symbol type="id" name="big_picture" />
   <java-symbol type="id" name="big_text" />
   <java-symbol type="id" name="chronometer" />
@@ -3270,12 +3272,12 @@
   <java-symbol type="integer" name="default_data_warning_level_mb" />
   <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
   <java-symbol type="bool" name="config_sendPackageName" />
-  <java-symbol type="string" name="config_help_package_name_key" />
-  <java-symbol type="string" name="config_help_package_name_value" />
-  <java-symbol type="string" name="config_help_intent_extra_key" />
-  <java-symbol type="string" name="config_help_intent_name_key" />
-  <java-symbol type="string" name="config_feedback_intent_extra_key" />
-  <java-symbol type="string" name="config_feedback_intent_name_key" />
+  <java-symbol type="string" name="config_helpPackageNameKey" />
+  <java-symbol type="string" name="config_helpPackageNameValue" />
+  <java-symbol type="string" name="config_helpIntentExtraKey" />
+  <java-symbol type="string" name="config_helpIntentNameKey" />
+  <java-symbol type="string" name="config_feedbackIntentExtraKey" />
+  <java-symbol type="string" name="config_feedbackIntentNameKey" />
 
   <java-symbol type="array" name="config_hideWhenDisabled_packageNames" />
 
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index fb78b3b..7b3d940 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -109,12 +109,12 @@
     <!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
          http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements,
          visual voicemail code for Orange: 21101 -->
-    <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366" />
+    <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101|20366|555|2051" />
 
     <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
          http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
          visual voicemail code for EE: 887 -->
-    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174|7726|37726" />
+    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174|7726|37726|88555|9017|9018" />
 
     <!-- Georgia: 4 digits, known premium codes listed -->
     <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
@@ -189,11 +189,14 @@
     <!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
     <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223" />
 
+    <!-- Nigeria -->
+    <shortcode country="ng" pattern="\\d{1,5}" free="2441" />
+
     <!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
     <shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" />
 
     <!-- New Zealand: 3-4 digits, known premium codes listed -->
-    <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="3067|3068|4053" />
+    <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|2141|3067|3068|3110|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" />
 
     <!-- Peru: 4-5 digits (not confirmed), known premium codes listed -->
     <shortcode country="pe" pattern="\\d{4,5}" free="9963" />
@@ -209,7 +212,7 @@
 
     <!-- Portugal: 5 digits, plus EU:
          http://clients.txtnation.com/entries/158326-portugal-premium-sms-short-code-regulations -->
-    <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}|1262" />
+    <shortcode country="pt" premium="6[1289]\\d{3}" free="116\\d{3}|1262|12666" />
 
     <!-- Qatar: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="qa" pattern="\\d{1,5}" free="92451" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index e0d5393..041fb7e 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -47,7 +47,6 @@
 
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner \
-    conscrypt \
     telephony-common \
     org.apache.http.legacy \
     android.test.base \
@@ -67,10 +66,6 @@
 
 # Disable AAPT2 because the hacks below depend on the AAPT rules implementation
 LOCAL_USE_AAPT2 := false
-# When AAPT2 is enabled it will need --warn-manifest-validation to fix:
-# frameworks/base/core/tests/coretests/AndroidManifest.xml:26: error: unknown element <meta-data> found.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-# LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
 # Rules to copy all the test apks to the intermediate raw resource directory
diff --git a/core/tests/coretests/apks/install_multi_package/Android.mk b/core/tests/coretests/apks/install_multi_package/Android.mk
index 9727593..3f163de 100644
--- a/core/tests/coretests/apks/install_multi_package/Android.mk
+++ b/core/tests/coretests/apks/install_multi_package/Android.mk
@@ -8,10 +8,6 @@
 LOCAL_PACKAGE_NAME := install_multi_package
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_multi_package/AndroidManifest.xml:46: error: unexpected element <package> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(FrameworkCoreTests_BUILD_PACKAGE)
 #include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.mk b/core/tests/coretests/apks/install_verifier_bad/Android.mk
index 679327c..745b4d3 100644
--- a/core/tests/coretests/apks/install_verifier_bad/Android.mk
+++ b/core/tests/coretests/apks/install_verifier_bad/Android.mk
@@ -6,9 +6,5 @@
 LOCAL_PACKAGE_NAME := install_verifier_bad
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml:19: error: unexpected element <package-verifier> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_verifier_good/Android.mk b/core/tests/coretests/apks/install_verifier_good/Android.mk
index 7d621b3..150fd8d 100644
--- a/core/tests/coretests/apks/install_verifier_good/Android.mk
+++ b/core/tests/coretests/apks/install_verifier_good/Android.mk
@@ -6,9 +6,5 @@
 LOCAL_PACKAGE_NAME := install_verifier_good
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml:19: error: unexpected element <package-verifier> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
index 584257b..e248a77 100644
--- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -45,7 +45,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
-import libcore.io.IoUtils;
+import libcore.testing.io.TestIoUtils;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -63,7 +63,7 @@
 
     @Before
     public void setUp() {
-        mTmpDir = IoUtils.createTemporaryDirectory("DexMetadataHelperTest");
+        mTmpDir = TestIoUtils.createTemporaryDirectory("DexMetadataHelperTest");
     }
 
     @After
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 20fe162..80281b6 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -48,7 +48,6 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 
-import libcore.io.IoUtils;
 import libcore.io.Streams;
 
 import com.google.android.collect.Sets;
@@ -95,7 +94,7 @@
 
     @After
     public void tearDown() throws Exception {
-        IoUtils.deleteContents(mDir);
+        FileUtils.deleteContents(mDir);
         FileUtils.deleteContents(mTarget);
     }
 
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 632c37f..60abd94 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -450,7 +450,6 @@
                     Settings.Global.GPU_DEBUG_APP,
                     Settings.Global.GPU_DEBUG_LAYERS,
                     Settings.Global.ANGLE_ENABLED_APP,
-                    Settings.Global.GPU_DEBUG_LAYER_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index f3d6013..3d15eb9 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -73,7 +73,7 @@
         assertEquals(0, mt.getWidths().size());
         assertEquals(0, mt.getSpanEndCache().size());
         assertEquals(0, mt.getFontMetrics().size());
-        assertNull(mt.getNativeMeasuredParagraph());
+        assertNull(mt.getMeasuredText());
 
         // Recycle it
         MeasuredParagraph mt2 = MeasuredParagraph.buildForBidi("_VVV_", 1, 4, RTL, mt);
@@ -85,7 +85,7 @@
         assertEquals(0, mt2.getWidths().size());
         assertEquals(0, mt2.getSpanEndCache().size());
         assertEquals(0, mt2.getFontMetrics().size());
-        assertNull(mt.getNativeMeasuredParagraph());
+        assertNull(mt.getMeasuredText());
 
         mt2.recycle();
     }
@@ -107,7 +107,7 @@
         assertEquals(10, mt.getWidths().get(2), 0);
         assertEquals(0, mt.getSpanEndCache().size());
         assertEquals(0, mt.getFontMetrics().size());
-        assertNull(mt.getNativeMeasuredParagraph());
+        assertNull(mt.getMeasuredText());
 
         // Recycle it
         MeasuredParagraph mt2 =
@@ -124,7 +124,7 @@
         assertEquals(5, mt2.getWidths().get(2), 0);
         assertEquals(0, mt2.getSpanEndCache().size());
         assertEquals(0, mt2.getFontMetrics().size());
-        assertNull(mt.getNativeMeasuredParagraph());
+        assertNull(mt.getMeasuredText());
 
         mt2.recycle();
     }
@@ -144,7 +144,7 @@
         assertEquals(1, mt.getSpanEndCache().size());
         assertEquals(3, mt.getSpanEndCache().get(0));
         assertNotEquals(0, mt.getFontMetrics().size());
-        assertNotNull(mt.getNativeMeasuredParagraph());
+        assertNotNull(mt.getMeasuredText());
 
         // Recycle it
         MeasuredParagraph mt2 =
@@ -159,7 +159,7 @@
         assertEquals(1, mt2.getSpanEndCache().size());
         assertEquals(4, mt2.getSpanEndCache().get(0));
         assertNotEquals(0, mt2.getFontMetrics().size());
-        assertNotNull(mt.getNativeMeasuredParagraph());
+        assertNotNull(mt.getMeasuredText());
 
         mt2.recycle();
     }
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index f8e3b4d..872b71a 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -117,7 +117,7 @@
     @Test
     public void testFormatSameDayTime() {
         // This test assumes a default DateFormat.is24Hour setting.
-        DateFormat.is24Hour = null;
+        DateFormat.set24HourTimePref(null);
         Date date = new Date(109, 0, 19, 3, 30, 15);
         long fixedTime = date.getTime();
 
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index c8d994c..8e4f2cd 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -103,6 +103,18 @@
                 equalTo(new Rect[]{ZERO_RECT, boundTop, ZERO_RECT, boundBottom}));
     }
 
+    @Test
+    public void testExtractBoundsFromList_nullBoundingRects() {
+        Rect safeInsets = new Rect(0, 0, 0, 0);
+        assertThat(extractBoundsFromList(safeInsets, null /* boundingRects */),
+                equalTo(new Rect[]{ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT}));
+    }
+
+    @Test
+    public void testExtractBoundsFromList_nullSafeInsets() {
+        assertThat(extractBoundsFromList(null /* safeInsets */, Collections.emptyList()),
+                equalTo(new Rect[]{ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT}));
+    }
 
     @Test
     public void hasCutout() throws Exception {
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 69d2828..506e544 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -45,7 +45,7 @@
     // The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
     // See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
     // and assertAccessibilityNodeInfoCleared in that class.
-    private static final int NUM_MARSHALLED_PROPERTIES = 33;
+    private static final int NUM_MARSHALLED_PROPERTIES = 34;
 
     /**
      * The number of properties that are purposely not marshalled
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index 0c8dd9d..f637b7c 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -77,9 +77,13 @@
 
         Message message = mHandlerFirst.obtainMessage(1000);
         message.workSourceUid = 1000;
+        message.when = looperStats.getSystemUptimeMillis();
+
+        looperStats.tickUptime(30);
         Object token = looperStats.messageDispatchStarting();
         looperStats.tickRealtime(100);
         looperStats.tickThreadTime(10);
+        looperStats.tickUptime(200);
         looperStats.messageDispatched(token, message);
 
         List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
@@ -98,6 +102,10 @@
         assertThat(entry.maxLatencyMicros).isEqualTo(100);
         assertThat(entry.cpuUsageMicros).isEqualTo(10);
         assertThat(entry.maxCpuUsageMicros).isEqualTo(10);
+        assertThat(entry.recordedDelayMessageCount).isEqualTo(1);
+        assertThat(entry.delayMillis).isEqualTo(30);
+        assertThat(entry.maxDelayMillis).isEqualTo(30);
+
     }
 
     @Test
@@ -215,6 +223,56 @@
     }
 
     @Test
+    public void testDispatchDelayIsRecorded() {
+        TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+        // Dispatched right on time.
+        Message message1 = mHandlerFirst.obtainMessage(1000);
+        message1.when = looperStats.getSystemUptimeMillis();
+        Object token1 = looperStats.messageDispatchStarting();
+        looperStats.tickUptime(10);
+        looperStats.messageDispatched(token1, message1);
+
+        // Dispatched 100ms late.
+        Message message2 = mHandlerFirst.obtainMessage(1000);
+        message2.when = looperStats.getSystemUptimeMillis() - 100;
+        Object token2 = looperStats.messageDispatchStarting();
+        looperStats.tickUptime(10);
+        looperStats.messageDispatched(token2, message2);
+
+        // No target dispatching time.
+        Message message3 = mHandlerFirst.obtainMessage(1000);
+        message3.when = 0;
+        Object token3 = looperStats.messageDispatchStarting();
+        looperStats.tickUptime(10);
+        looperStats.messageDispatched(token3, message3);
+
+        // Dispatched too soon (should never happen).
+        Message message4 = mHandlerFirst.obtainMessage(1000);
+        message4.when = looperStats.getSystemUptimeMillis() + 200;
+        Object token4 = looperStats.messageDispatchStarting();
+        looperStats.tickUptime(10);
+        looperStats.messageDispatched(token4, message4);
+
+        // Dispatched 300ms late.
+        Message message5 = mHandlerFirst.obtainMessage(1000);
+        message5.when = looperStats.getSystemUptimeMillis() - 300;
+        Object token5 = looperStats.messageDispatchStarting();
+        looperStats.tickUptime(10);
+        looperStats.messageDispatched(token5, message5);
+
+        List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+        assertThat(entries).hasSize(1);
+
+        LooperStats.ExportedEntry entry = entries.get(0);
+        assertThat(entry.messageCount).isEqualTo(5);
+        assertThat(entry.recordedMessageCount).isEqualTo(5);
+        assertThat(entry.recordedDelayMessageCount).isEqualTo(4);
+        assertThat(entry.delayMillis).isEqualTo(400);
+        assertThat(entry.maxDelayMillis).isEqualTo(300);
+    }
+
+    @Test
     public void testDataNotCollectedBeforeDeviceStateSet() {
         TestableLooperStats looperStats = new TestableLooperStats(1, 100);
         looperStats.setDeviceState(null);
@@ -385,6 +443,7 @@
         private int mCount;
         private long mRealtimeMicros;
         private long mThreadTimeMicros;
+        private long mUptimeMillis;
         private int mSamplingInterval;
 
         TestableLooperStats(int samplingInterval, int sizeCap) {
@@ -401,6 +460,10 @@
             mThreadTimeMicros += micros;
         }
 
+        void tickUptime(long millis) {
+            mUptimeMillis += millis;
+        }
+
         @Override
         protected long getElapsedRealtimeMicro() {
             return INITIAL_MICROS + mRealtimeMicros;
@@ -412,6 +475,11 @@
         }
 
         @Override
+        protected long getSystemUptimeMillis() {
+            return INITIAL_MICROS / 1000 + mUptimeMillis;
+        }
+
+        @Override
         protected boolean shouldCollectDetailedData() {
             return mCount++ % mSamplingInterval == 0;
         }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ed24543..44f8737 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -325,6 +325,7 @@
         <permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
+        <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.REGISTER_CALL_PROVIDER"/>
         <permission name="android.permission.REGISTER_CONNECTION_MANAGER"/>
         <permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 0885a05..ea0a109 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -549,7 +549,7 @@
                             contextStart - paraStart,
                             contextEnd - contextStart,
                             x, y, isRtl, paint.getNativeInstance(),
-                            mp.getNativeMeasuredParagraph().getNativePtr());
+                            mp.getMeasuredText().getNativePtr());
                     return;
                 }
             }
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index fb30ca2..4de7ca7 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -520,7 +520,7 @@
                             contextStart - paraStart,
                             contextEnd - contextStart,
                             x, y, isRtl, paint.getNativeInstance(),
-                            mp.getNativeMeasuredParagraph().getNativePtr());
+                            mp.getMeasuredText().getNativePtr());
                     return;
                 }
             }
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 8414d6a..b65fb9c 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -2525,9 +2525,7 @@
                     gamma == 1.0 ? DoubleUnaryOperator.identity() :
                             x -> Math.pow(x < 0.0 ? 0.0 : x, gamma),
                     min, max, id);
-            mTransferParameters = gamma == 1.0 ?
-                    new TransferParameters(0.0, 0.0, 1.0, 1.0 + Math.ulp(1.0f), gamma) :
-                    new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
+            mTransferParameters = new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
         }
 
         /**
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 7efe522..f41cc7e 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -21,7 +21,6 @@
 import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -570,7 +569,7 @@
      * Version of createWithResource that takes Resources. Do not use.
      * @hide
      */
-    @SystemApi
+    @UnsupportedAppUsage
     public static Icon createWithResource(Resources res, @DrawableRes int resId) {
         if (res == null) {
             throw new IllegalArgumentException("Resource must not be null.");
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 3821bc7..21ce1b8 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -27,7 +27,6 @@
 import android.system.OsConstants;
 import dalvik.system.CloseGuard;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 import java.io.IOException;
 
diff --git a/core/java/android/text/NativeLineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
similarity index 67%
rename from core/java/android/text/NativeLineBreaker.java
rename to graphics/java/android/graphics/text/LineBreaker.java
index 94e10e8..8d38f96 100644
--- a/core/java/android/text/NativeLineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.text;
+package android.graphics.text;
 
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
@@ -32,11 +32,57 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * A native implementation of the line breaker.
- * TODO: Consider to make this class public.
- * @hide
+ * Provides automatic line breaking for a <em>single</em> paragraph.
+ *
+ * <p>
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * String text = "Hello, Android.";
+ *
+ * // Prepare the measured text
+ * MeasuredText mt = new MeasuredText.Builder(text.toCharArray())
+ *     .addStyleRun(paint, 0, text.length(), false)  // Use paint for whole paragraph.
+ *     .build();
+ *
+ * LineBreaker lb = new LineBreaker.Builder()
+ *     // Use simple line breaker
+ *     .setBreakStrategy(LineBreaker.BREAK_STRATEGY_SIMPLE)
+ *     // Do not add hyphenation.
+ *     .setHyphenationFrequency(LineBreaker.HYPHENATION_FREQUENCY_NONE)
+ *     // Build the LineBreaker
+ *     .build();
+ *
+ * ParagraphConstraints c = new ParagraphConstraints();
+ * c.setWidth(240);  // Set the line wieth as 1024px
+ *
+ * // Do the line breaking
+ * Result r = lb.computeLineBreaks(mt, c, 0);
+ *
+ * // Compute the total height of the text.
+ * float totalHeight = 0;
+ * for (int i = 0; i < r.getLineCount(); ++i) {  // iterate over the lines
+ *    totalHeight += r.getLineDescent(i) - r.getLineAscent(i);
+ * }
+ *
+ * // Draw text to the canvas
+ * Bitmap bmp = new Bitmap.createBitmap(240, totalHeight, Bitmap.Config.ARGB_8888);
+ * Canvas c = new Canvas(bmp);
+ * float yOffset = 0f;
+ * int prevOffset = 0;
+ * for (int i = 0; i < r.getLineCount(); ++i) {  // iterate over the lines
+ *     int nextOffset = r.getLineBreakOffset(i);
+ *     c.drawText(text, prevOffset, nextOffset, 0f, yOffset, paint);
+ *
+ *     prevOffset = nextOffset;
+ *     yOffset += r.getLineDescent(i) - r.getLineAscent(i);
+ * }
+ * </code>
+ * </pre>
+ * </p>
  */
-public class NativeLineBreaker {
+public class LineBreaker {
+    /** @hide */
     @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
             BREAK_STRATEGY_SIMPLE,
             BREAK_STRATEGY_HIGH_QUALITY,
@@ -46,25 +92,33 @@
     public @interface BreakStrategy {}
 
     /**
-     * Value for break strategy indicating simple line breaking. Automatic hyphens are not added
-     * (though soft hyphens are respected), and modifying text generally doesn't affect the layout
-     * before it (which yields a more consistent user experience when editing), but layout may not
-     * be the highest quality.
+     * Value for break strategy indicating simple line breaking.
+     *
+     * The line breaker puts words to the line as much as possible and breaks line if no more words
+     * can fit into the same line. Automatic hyphens are only added when a line has a single word
+     * and that word is longer than line width. This is the fastest break strategy and ideal for
+     * editor.
      */
     public static final int BREAK_STRATEGY_SIMPLE = 0;
 
     /**
-     * Value for break strategy indicating high quality line breaking, including automatic
-     * hyphenation and doing whole-paragraph optimization of line breaks.
+     * Value for break strategy indicating high quality line breaking.
+     *
+     * With this option line breaker does whole-paragraph optimization for more readable text, and
+     * also applies automatic hyphenation when required.
      */
     public static final int BREAK_STRATEGY_HIGH_QUALITY = 1;
 
     /**
-     * Value for break strategy indicating balanced line breaking. The breaks are chosen to
-     * make all lines as close to the same length as possible, including automatic hyphenation.
+     * Value for break strategy indicating balanced line breaking.
+     *
+     * The line breaker does whole-paragraph optimization for making all lines similar length, and
+     * also applies automatic hyphenation when required. This break strategy is good for small
+     * screen devices such as watch screens.
      */
     public static final int BREAK_STRATEGY_BALANCED = 2;
 
+    /** @hide */
     @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
             HYPHENATION_FREQUENCY_NORMAL,
             HYPHENATION_FREQUENCY_FULL,
@@ -74,28 +128,32 @@
     public @interface HyphenationFrequency {}
 
     /**
-     * Value for hyphenation frequency indicating no automatic hyphenation. Useful
-     * for backward compatibility, and for cases where the automatic hyphenation algorithm results
-     * in incorrect hyphenation. Mid-word breaks may still happen when a word is wider than the
-     * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
-     * as suggestions for potential line breaks.
+     * Value for hyphenation frequency indicating no automatic hyphenation.
+     *
+     * Using this option disables auto hyphenation which results in better text layout performance.
+     * A word may be broken without hyphens when a line has a single word and that word is longer
+     * than line width. Soft hyphens are ignored and will not be used as suggestions for potential
+     * line breaks.
      */
     public static final int HYPHENATION_FREQUENCY_NONE = 0;
 
     /**
-     * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
-     * is a conservative default. Useful for informal cases, such as short sentences or chat
+     * Value for hyphenation frequency indicating a light amount of automatic hyphenation.
+     *
+     * This hyphenation frequency is useful for informal cases, such as short sentences or chat
      * messages.
      */
     public static final int HYPHENATION_FREQUENCY_NORMAL = 1;
 
     /**
-     * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
-     * in typography. Useful for running text and where it's important to put the maximum amount of
-     * text in a screen with limited space.
+     * Value for hyphenation frequency indicating the full amount of automatic hyphenation.
+     *
+     * This hyphenation frequency is useful for running text and where it's important to put the
+     * maximum amount of text in a screen with limited space.
      */
     public static final int HYPHENATION_FREQUENCY_FULL = 2;
 
+    /** @hide */
     @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = {
             JUSTIFICATION_MODE_NONE,
             JUSTIFICATION_MODE_INTER_WORD
@@ -114,7 +172,7 @@
     public static final int JUSTIFICATION_MODE_INTER_WORD = 1;
 
     /**
-     * A builder class of NativeLineBreaker.
+     * Helper class for creating a {@link LineBreaker}.
      */
     public static class Builder {
         private @BreakStrategy int mBreakStrategy = BREAK_STRATEGY_SIMPLE;
@@ -123,12 +181,10 @@
         private @Nullable int[] mIndents = null;
 
         /**
-         * Construct a builder class.
-         */
-        public Builder() {}
-
-        /**
          * Set break strategy.
+         *
+         * You can change the line breaking behavior by setting break strategy. The default value is
+         * {@link #BREAK_STRATEGY_SIMPLE}.
          */
         public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
             mBreakStrategy = breakStrategy;
@@ -137,6 +193,9 @@
 
         /**
          * Set hyphenation frequency.
+         *
+         * You can change the amount of automatic hyphenation used. The default value is
+         * {@link #HYPHENATION_FREQUENCY_NONE}.
          */
         public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) {
             mHyphenationFrequency = hyphenationFrequency;
@@ -145,6 +204,10 @@
 
         /**
          * Set whether the text is justified.
+         *
+         * By setting {@link #JUSTIFICATION_MODE_INTER_WORD}, the line breaker will change the
+         * internal parameters for justification.
+         * The default value is {@link #JUSTIFICATION_MODE_NONE}
          */
         public Builder setJustified(@JustificationMode int justified) {
             mJustified = justified;
@@ -152,9 +215,11 @@
         }
 
         /**
-         * Set indents for entire text.
+         * Set indents.
          *
-         * Sets the total (left + right) indents in pixel per lines.
+         * The supplied array provides the total amount of indentation per line, in pixel. This
+         * amount is the sum of both left and right indentations. For lines past the last element in
+         * the array, the indentation amount of the last element is used.
          */
         public Builder setIndents(@Nullable int[] indents) {
             mIndents = indents;
@@ -162,11 +227,12 @@
         }
 
         /**
-         * Returns the NativeLineBreaker with given parameters.
+         * Build a new LineBreaker with given parameters.
+         *
+         * You can reuse the Builder instance even after calling this method.
          */
-        NativeLineBreaker build() {
-            return new NativeLineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified,
-                    mIndents);
+        public LineBreaker build() {
+            return new LineBreaker(mBreakStrategy, mHyphenationFrequency, mJustified, mIndents);
         }
     }
 
@@ -184,8 +250,10 @@
 
         /**
          * Set width for this paragraph.
+         *
+         * @see #getWidth()
          */
-        public void setWidth(@FloatRange(from = 0.0f) float width) {
+        public void setWidth(@Px @FloatRange(from = 0.0f) float width) {
             mWidth = width;
         }
 
@@ -194,9 +262,11 @@
          *
          * @param firstWidth the line width of the starting of the paragraph
          * @param firstWidthLineCount the number of lines that applies the firstWidth
+         * @see #getFirstWidth()
+         * @see #getFirstWidthLineCount()
          */
-        public void setIndent(@FloatRange(from = 0.0f) float firstWidth,
-                @IntRange(from = 0) int firstWidthLineCount) {
+        public void setIndent(@Px @FloatRange(from = 0.0f) float firstWidth,
+                @Px @IntRange(from = 0) int firstWidthLineCount) {
             mFirstWidth = firstWidth;
             mFirstWidthLineCount = firstWidthLineCount;
         }
@@ -206,16 +276,21 @@
          *
          * @param tabStops the array of pixels of tap stopping position
          * @param defaultTabStop pixels of the default tab stopping position
+         * @see #getTabStops()
+         * @see #getDefaultTabStop()
          */
-        public void setTabStops(@Nullable int[] tabStops, @IntRange(from = 0) int defaultTabStop) {
+        public void setTabStops(@Nullable int[] tabStops,
+                @Px @IntRange(from = 0) int defaultTabStop) {
             mVariableTabStops = tabStops;
             mDefaultTabStop = defaultTabStop;
         }
 
         /**
          * Return the width for this paragraph in pixels.
+         *
+         * @see #setWidth(float)
          */
-        public @FloatRange(from = 0.0f) float getWidth() {
+        public @Px @FloatRange(from = 0.0f) float getWidth() {
             return mWidth;
         }
 
@@ -224,7 +299,7 @@
          *
          * @see #setIndent(float, int)
          */
-        public @FloatRange(from = 0.0f) float getFirstWidth() {
+        public @Px @FloatRange(from = 0.0f) float getFirstWidth() {
             return mFirstWidth;
         }
 
@@ -233,7 +308,7 @@
          *
          * @see #setIndent(float, int)
          */
-        public @IntRange(from = 0) int getFirstWidthLineCount() {
+        public @Px @IntRange(from = 0) int getFirstWidthLineCount() {
             return mFirstWidthLineCount;
         }
 
@@ -251,13 +326,14 @@
          *
          * @see #setTabStop(int[], int)
          */
-        public @IntRange(from = 0) int getDefaultTabStop() {
+        public @Px @IntRange(from = 0) int getDefaultTabStop() {
             return mDefaultTabStop;
         }
     }
 
     /**
-     * A result object of a line breaking
+     * Holds the result of the {@link LineBreaker#computeLineBreaks line breaking algorithm}.
+     * @see LineBreaker#computeLineBreaks
      */
     public static class Result {
         // Following two contstant must be synced with minikin's line breaker.
@@ -274,7 +350,7 @@
         }
 
         /**
-         * Returns a number of line count.
+         * Returns the number of lines in the paragraph.
          *
          * @return number of lines
          */
@@ -283,7 +359,7 @@
         }
 
         /**
-         * Returns a break offset of the line.
+         * Returns character offset of the break for a given line.
          *
          * @param lineIndex an index of the line.
          * @return the break offset.
@@ -293,17 +369,17 @@
         }
 
         /**
-         * Returns a width of the line in pixels.
+         * Returns width of a given line in pixels.
          *
          * @param lineIndex an index of the line.
-         * @return a width of the line in pixexls
+         * @return width of the line in pixels
          */
         public @Px float getLineWidth(@IntRange(from = 0) int lineIndex) {
             return nGetLineWidth(mPtr, lineIndex);
         }
 
         /**
-         * Returns an entier font ascent of the line in pixels.
+         * Returns font ascent of the line in pixels.
          *
          * @param lineIndex an index of the line.
          * @return an entier font ascent of the line in pixels.
@@ -313,7 +389,7 @@
         }
 
         /**
-         * Returns an entier font descent of the line in pixels.
+         * Returns font descent of the line in pixels.
          *
          * @param lineIndex an index of the line.
          * @return an entier font descent of the line in pixels.
@@ -337,6 +413,7 @@
          *
          * @param lineIndex an index of the line.
          * @return a packed hyphen edit for the line.
+         *
          * @see android.text.Hyphenator#unpackStartHyphenEdit(int)
          * @see android.text.Hyphenator#unpackEndHyphenEdit(int)
          * @see android.text.Hyphenator#packHyphenEdit(int,int)
@@ -347,14 +424,14 @@
     }
 
     private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            NativeLineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64);
+            LineBreaker.class.getClassLoader(), nGetReleaseFunc(), 64);
 
     private final long mNativePtr;
 
     /**
      * Use Builder instead.
      */
-    private NativeLineBreaker(@BreakStrategy int breakStrategy,
+    private LineBreaker(@BreakStrategy int breakStrategy,
             @HyphenationFrequency int hyphenationFrequency, @JustificationMode int justify,
             @Nullable int[] indents) {
         mNativePtr = nInit(breakStrategy, hyphenationFrequency,
@@ -372,7 +449,7 @@
      * @param lineNumber a line number of this paragraph
      */
     public Result computeLineBreaks(
-            @NonNull NativeMeasuredParagraph measuredPara,
+            @NonNull MeasuredText measuredPara,
             @NonNull ParagraphConstraints constraints,
             @IntRange(from = 0) int lineNumber) {
         return new Result(nComputeLineBreaks(
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
new file mode 100644
index 0000000..36e7028
--- /dev/null
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2010 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.graphics.text;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Px;
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import com.android.internal.util.Preconditions;
+
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+/**
+ * Result of text shaping of the single paragraph string.
+ */
+public class MeasuredText {
+    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+            MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024);
+
+    private long mNativePtr;
+    private @NonNull char[] mChars;
+
+    // Use builder instead.
+    private MeasuredText(long ptr, @NonNull char[] chars) {
+        mNativePtr = ptr;
+        mChars = chars;
+    }
+
+    /**
+     * Returns the characters in the paragraph used to compute this MeasuredText instance.
+     */
+    public @NonNull char[] getChars() {
+        return mChars;
+    }
+
+    /**
+     * Returns the width of a given range.
+     *
+     * @param start an inclusive start index of the range
+     * @param end an exclusive end index of the range
+     */
+    public @FloatRange(from = 0.0) @Px float getWidth(
+            @IntRange(from = 0) int start, @IntRange(from = 0) int end) {
+        Preconditions.checkArgument(0 <= start && start <= mChars.length,
+                "start(" + start + ") must be 0 <= start <= " + mChars.length);
+        Preconditions.checkArgument(0 <= end && end <= mChars.length,
+                "end(" + end + ") must be 0 <= end <= " + mChars.length);
+        Preconditions.checkArgument(start <= end,
+                "start(" + start + ") is larger than end(" + end + ")");
+        return nGetWidth(mNativePtr, start, end);
+    }
+
+    /**
+     * Returns a memory usage of the native object.
+     *
+     * @hide
+     */
+    public int getMemoryUsage() {
+        return nGetMemoryUsage(mNativePtr);
+    }
+
+    /**
+     * Retrieves the boundary box of the given range
+     *
+     * @param start an inclusive start index of the range
+     * @param end an exclusive end index of the range
+     * @param rect an output parameter
+     */
+    public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
+            @NonNull Rect rect) {
+        Preconditions.checkArgument(0 <= start && start <= mChars.length,
+                "start(" + start + ") must be 0 <= start <= " + mChars.length);
+        Preconditions.checkArgument(0 <= end && end <= mChars.length,
+                "end(" + end + ") must be 0 <= end <= " + mChars.length);
+        Preconditions.checkArgument(start <= end,
+                "start(" + start + ") is larger than end(" + end + ")");
+        Preconditions.checkNotNull(rect);
+        nGetBounds(mNativePtr, mChars, start, end, rect);
+    }
+
+    /**
+     * Returns the width of the character at the given offset.
+     *
+     * @param offset an offset of the character.
+     */
+    public @FloatRange(from = 0.0f) @Px float getCharWidthAt(@IntRange(from = 0) int offset) {
+        Preconditions.checkArgument(0 <= offset && offset < mChars.length,
+                "offset(" + offset + ") is larger than text length: " + mChars.length);
+        return nGetCharWidthAt(mNativePtr, offset);
+    }
+
+    /**
+     * Returns a native pointer of the underlying native object.
+     *
+     * @hide
+     */
+    public long getNativePtr() {
+        return mNativePtr;
+    }
+
+    @CriticalNative
+    private static native float nGetWidth(/* Non Zero */ long nativePtr,
+                                         @IntRange(from = 0) int start,
+                                         @IntRange(from = 0) int end);
+
+    @CriticalNative
+    private static native /* Non Zero */ long nGetReleaseFunc();
+
+    @CriticalNative
+    private static native int nGetMemoryUsage(/* Non Zero */ long nativePtr);
+
+    private static native void nGetBounds(long nativePtr, char[] buf, int start, int end,
+            Rect rect);
+
+    @CriticalNative
+    private static native float nGetCharWidthAt(long nativePtr, int offset);
+
+    /**
+     * Helper class for creating a {@link MeasuredText}.
+     */
+    public static class Builder {
+        private long mNativePtr;
+
+        private final @NonNull char[] mText;
+        private boolean mComputeHyphenation = false;
+        private boolean mComputeLayout = true;
+
+        /**
+         * Construct a builder.
+         *
+         * The MeasuredText returned by build method will hold a reference of the text. Developer is
+         * not supposed to modify the text.
+         *
+         * @param text a text
+         */
+        public Builder(@NonNull char[] text) {
+            Preconditions.checkNotNull(text);
+            mText = text;
+            mNativePtr = nInitBuilder();
+        }
+
+        /**
+         * Apply styles to the given range.
+         *
+         * @param paint a paint
+         * @param start an inclusive start index of the range
+         * @param end an exclusive end index of the range
+         * @param isRtl true if the text is in RTL context, otherwise false.
+         */
+        public Builder addStyleRun(@NonNull Paint paint,
+                @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl) {
+            Preconditions.checkNotNull(paint);
+            nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl);
+            return this;
+        }
+
+        /**
+         * Used to inform the text layout that the given range is replaced with the object of given
+         * width.
+         *
+         * Informs the layout engine that the given range should not be processed, instead the
+         * provided width should be used for calculating the width of that range.
+         *
+         * @param start an inclusive start index of the range
+         * @param end an exclusive end index of the range
+         * @param width a replacement width of the range
+         */
+        public Builder addReplacementRun(@NonNull Paint paint,
+                @IntRange(from = 0) int start, @IntRange(from = 0) int end,
+                @FloatRange(from = 0) float width) {
+            nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width);
+            return this;
+        }
+
+        /**
+         * By passing true to this method, the build method will compute all possible hyphenation
+         * pieces as well.
+         *
+         * If you don't want to use automatic hyphenation, you can pass false to this method and
+         * save the computation time of hyphenation. The default value is false.
+         *
+         * Even if you pass false to this method, you can still enable automatic hyphenation of
+         * LineBreaker but line break computation becomes slower.
+         *
+         * @param computeHyphenation true if you want to use automatic hyphenations.
+         */
+        public Builder setComputeHyphenation(boolean computeHyphenation) {
+            mComputeHyphenation = computeHyphenation;
+            return this;
+        }
+
+        /**
+         * By passing true to this method, the build method will compute all full layout
+         * information.
+         *
+         * If you don't use {@link MeasuredText#getBounds(int,int,android.graphics.Rect)}, you can
+         * pass false to this method and save the memory spaces. The default value is true.
+         *
+         * Even if you pass false to this method, you can still call getBounds but it becomes
+         * slower.
+         *
+         * @param computeLayout true if you want to retrieve full layout info, e.g. bbox.
+         */
+        public Builder setComputeLayout(boolean computeLayout) {
+            mComputeLayout = computeLayout;
+            return this;
+        }
+
+        /**
+         * Creates a MeasuredText.
+         *
+         * Once you called build() method, you can't reuse the Builder class again.
+         * @throws IllegalStateException if this Builder is reused.
+         */
+        public MeasuredText build() {
+            if (mNativePtr == 0) {
+                throw new IllegalStateException("Builder can not be reused.");
+            }
+            try {
+                long ptr = nBuildMeasuredText(mNativePtr, mText, mComputeHyphenation,
+                        mComputeLayout);
+                MeasuredText res = new MeasuredText(ptr, mText);
+                sRegistry.registerNativeAllocation(res, ptr);
+                return res;
+            } finally {
+                nFreeBuilder(mNativePtr);
+                mNativePtr = 0;
+            }
+        }
+
+        private static native /* Non Zero */ long nInitBuilder();
+
+        /**
+         * Apply style to make native measured text.
+         *
+         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
+         * @param paintPtr The native paint pointer to be applied.
+         * @param start The start offset in the copied buffer.
+         * @param end The end offset in the copied buffer.
+         * @param isRtl True if the text is RTL.
+         */
+        private static native void nAddStyleRun(/* Non Zero */ long nativeBuilderPtr,
+                                                /* Non Zero */ long paintPtr,
+                                                @IntRange(from = 0) int start,
+                                                @IntRange(from = 0) int end,
+                                                boolean isRtl);
+        /**
+         * Apply ReplacementRun to make native measured text.
+         *
+         * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
+         * @param paintPtr The native paint pointer to be applied.
+         * @param start The start offset in the copied buffer.
+         * @param end The end offset in the copied buffer.
+         * @param width The width of the replacement.
+         */
+        private static native void nAddReplacementRun(/* Non Zero */ long nativeBuilderPtr,
+                                                      /* Non Zero */ long paintPtr,
+                                                      @IntRange(from = 0) int start,
+                                                      @IntRange(from = 0) int end,
+                                                      @FloatRange(from = 0) float width);
+
+        private static native long nBuildMeasuredText(
+                /* Non Zero */ long nativeBuilderPtr,
+                @NonNull char[] text,
+                boolean computeHyphenation,
+                boolean computeLayout);
+
+        private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
+    }
+}
diff --git a/keystore/OWNERS b/keystore/OWNERS
new file mode 100644
index 0000000..a63ca46
--- /dev/null
+++ b/keystore/OWNERS
@@ -0,0 +1,4 @@
+jbires@google.com
+jdanis@google.com
+robbarnes@google.com
+swillden@google.com
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 74cab92..98af3eb 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -50,6 +50,7 @@
         "LocaleData.cpp",
         "misc.cpp",
         "ObbFile.cpp",
+        "PosixUtils.cpp",
         "ResourceTypes.cpp",
         "ResourceUtils.cpp",
         "StreamingZipInflater.cpp",
@@ -157,6 +158,7 @@
             srcs: [
                 "tests/BackupData_test.cpp",
                 "tests/ObbFile_test.cpp",
+                "tests/PosixUtils_test.cpp",
             ],
             shared_libs: common_test_libs + ["libui"],
         },
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 9c1629b..04cc5bb 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -67,10 +67,10 @@
 }
 
 bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
-                                 bool invalidate_caches) {
+                                 bool invalidate_caches, bool filter_incompatible_configs) {
   apk_assets_ = apk_assets;
   BuildDynamicRefTable();
-  RebuildFilterList();
+  RebuildFilterList(filter_incompatible_configs);
   if (invalidate_caches) {
     InvalidateCaches(static_cast<uint32_t>(-1));
   }
@@ -825,7 +825,7 @@
   return 0u;
 }
 
-void AssetManager2::RebuildFilterList() {
+void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) {
   for (PackageGroup& group : package_groups_) {
     for (ConfiguredPackage& impl : group.packages_) {
       // Destroy it.
@@ -841,7 +841,7 @@
         for (auto iter = spec->types; iter != iter_end; ++iter) {
           ResTable_config this_config;
           this_config.copyFromDtoH((*iter)->config);
-          if (this_config.match(configuration_)) {
+          if (!filter_incompatible_configs || this_config.match(configuration_)) {
             group.configurations.push_back(this_config);
             group.types.push_back(*iter);
           }
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c2740c9..68d216d 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -203,6 +203,39 @@
   return true;
 }
 
+LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei)
+    : loadedPackage_(lp),
+      typeIndex_(ti),
+      entryIndex_(ei),
+      typeIndexEnd_(lp->resource_ids_.size() + 1) {
+  while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) {
+    typeIndex_++;
+  }
+}
+
+LoadedPackage::iterator& LoadedPackage::iterator::operator++() {
+  while (typeIndex_ < typeIndexEnd_) {
+    if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) {
+      entryIndex_++;
+      break;
+    }
+    entryIndex_ = 0;
+    typeIndex_++;
+    if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) {
+      break;
+    }
+  }
+  return *this;
+}
+
+uint32_t LoadedPackage::iterator::operator*() const {
+  if (typeIndex_ >= typeIndexEnd_) {
+    return 0;
+  }
+  return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_,
+          entryIndex_);
+}
+
 const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
                                               uint16_t entry_index) {
   uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
@@ -488,6 +521,7 @@
         std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
         if (builder_ptr == nullptr) {
           builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+          loaded_package->resource_ids_.set(type_spec->id, entry_count);
         } else {
           LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
                                        type_spec->id);
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
new file mode 100644
index 0000000..df0dd7c
--- /dev/null
+++ b/libs/androidfw/PosixUtils.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.
+ */
+
+#ifdef _WIN32
+// nothing to see here
+#else
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "android-base/logging.h"
+
+#include "androidfw/PosixUtils.h"
+
+namespace {
+
+std::unique_ptr<std::string> ReadFile(int fd) {
+  std::unique_ptr<std::string> str(new std::string());
+  char buf[1024];
+  ssize_t r;
+  while ((r = read(fd, buf, sizeof(buf))) > 0) {
+    str->append(buf, r);
+  }
+  if (r != 0) {
+    return nullptr;
+  }
+  return str;
+}
+
+}
+
+namespace android {
+namespace util {
+
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv) {
+  int stdout[2];  // stdout[0] read, stdout[1] write
+  if (pipe(stdout) != 0) {
+    PLOG(ERROR) << "pipe";
+    return nullptr;
+  }
+
+  int stderr[2];  // stdout[0] read, stdout[1] write
+  if (pipe(stderr) != 0) {
+    PLOG(ERROR) << "pipe";
+    close(stdout[0]);
+    close(stdout[1]);
+    return nullptr;
+  }
+
+  char const** argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1));
+  for (size_t i = 0; i < argv.size(); i++) {
+    argv0[i] = argv[i].c_str();
+  }
+  argv0[argv.size()] = nullptr;
+  switch (fork()) {
+    case -1: // error
+      free(argv0);
+      PLOG(ERROR) << "fork";
+      return nullptr;
+    case 0: // child
+      close(stdout[0]);
+      if (dup2(stdout[1], STDOUT_FILENO) == -1) {
+        abort();
+      }
+      close(stderr[0]);
+      if (dup2(stderr[1], STDERR_FILENO) == -1) {
+        abort();
+      }
+      execvp(argv0[0], const_cast<char* const*>(argv0));
+      PLOG(ERROR) << "execv";
+      abort();
+    default: // parent
+      free(argv0);
+      close(stdout[1]);
+      close(stderr[1]);
+      int status;
+      wait(&status);
+      if (!WIFEXITED(status)) {
+          return nullptr;
+      }
+      std::unique_ptr<ProcResult> result(new ProcResult());
+      result->status = status;
+      const auto out = ReadFile(stdout[0]);
+      result->stdout = out ? *out : "";
+      close(stdout[0]);
+      const auto err = ReadFile(stderr[0]);
+      result->stderr = err ? *err : "";
+      close(stderr[0]);
+      return result;
+  }
+}
+
+} // namespace util
+} // namespace android
+#endif
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index ad31f69..2f0ee01 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -96,7 +96,12 @@
   // Only pass invalidate_caches=false when it is known that the structure
   // change in ApkAssets is due to a safe addition of resources with completely
   // new resource IDs.
-  bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
+  //
+  // Only pass in filter_incompatible_configs=false when you want to load all
+  // configurations (including incompatible ones) such as when constructing an
+  // idmap.
+  bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true,
+          bool filter_incompatible_configs = true);
 
   inline const std::vector<const ApkAssets*> GetApkAssets() const {
     return apk_assets_;
@@ -274,7 +279,7 @@
 
   // Triggers the re-construction of lists of types that match the set configuration.
   // This should always be called when mutating the AssetManager's configuration or ApkAssets set.
-  void RebuildFilterList();
+  void RebuildFilterList(bool filter_incompatible_configs = true);
 
   // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
   // been seen while traversing bag parents.
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 35ae5fc..349b379 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -78,6 +78,55 @@
 
 class LoadedPackage {
  public:
+  class iterator {
+   public:
+    iterator& operator=(const iterator& rhs) {
+      loadedPackage_ = rhs.loadedPackage_;
+      typeIndex_ = rhs.typeIndex_;
+      entryIndex_ = rhs.entryIndex_;
+      return *this;
+    }
+
+    bool operator==(const iterator& rhs) const {
+      return loadedPackage_ == rhs.loadedPackage_ &&
+             typeIndex_ == rhs.typeIndex_ &&
+             entryIndex_ == rhs.entryIndex_;
+    }
+
+    bool operator!=(const iterator& rhs) const {
+      return !(*this == rhs);
+    }
+
+    iterator operator++(int) {
+      size_t prevTypeIndex_ = typeIndex_;
+      size_t prevEntryIndex_ = entryIndex_;
+      operator++();
+      return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_);
+    }
+
+    iterator& operator++();
+
+    uint32_t operator*() const;
+
+   private:
+    friend class LoadedPackage;
+
+    iterator(const LoadedPackage* lp, size_t ti, size_t ei);
+
+    const LoadedPackage* loadedPackage_;
+    size_t typeIndex_;
+    size_t entryIndex_;
+    const size_t typeIndexEnd_;  // STL style end, so one past the last element
+  };
+
+  iterator begin() const {
+    return iterator(this, 0, 0);
+  }
+
+  iterator end() const {
+    return iterator(this, resource_ids_.size() + 1, 0);
+  }
+
   static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
                                                    const LoadedIdmap* loaded_idmap, bool system,
                                                    bool load_as_shared_library);
@@ -182,6 +231,7 @@
   bool overlay_ = false;
 
   ByteBucketArray<TypeSpecPtr> type_specs_;
+  ByteBucketArray<uint32_t> resource_ids_;
   std::vector<DynamicPackageEntry> dynamic_package_map_;
 };
 
diff --git a/libs/androidfw/include/androidfw/PosixUtils.h b/libs/androidfw/include/androidfw/PosixUtils.h
new file mode 100644
index 0000000..8fc3ee2
--- /dev/null
+++ b/libs/androidfw/include/androidfw/PosixUtils.h
@@ -0,0 +1,36 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace util {
+
+struct ProcResult {
+  int status;
+  std::string stdout;
+  std::string stderr;
+};
+
+// Fork, exec and wait for an external process. Return nullptr if the process could not be launched,
+// otherwise a ProcResult containing the external process' exit status and captured stdout and
+// stderr.
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv);
+
+} // namespace util
+} // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index cae632d..ffa4836 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -278,4 +278,52 @@
 // sizeof(Res_value) might not be backwards compatible.
 TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
 
+TEST(LoadedArscTest, ResourceIdentifierIterator) {
+  std::string contents;
+  ASSERT_TRUE(
+      ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+
+  std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+  EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
+
+  const auto& loaded_package = packages[0];
+  auto iter = loaded_package->begin();
+  auto end = loaded_package->end();
+
+  ASSERT_NE(end, iter);
+  ASSERT_EQ(0x7f010000u, *iter++);
+  ASSERT_EQ(0x7f010001u, *iter++);
+  ASSERT_EQ(0x7f020000u, *iter++);
+  ASSERT_EQ(0x7f020001u, *iter++);
+  ASSERT_EQ(0x7f030000u, *iter++);
+  ASSERT_EQ(0x7f030001u, *iter++);
+  ASSERT_EQ(0x7f030002u, *iter++);  // note: string without default, excluded by aapt2 dump
+  ASSERT_EQ(0x7f040000u, *iter++);
+  ASSERT_EQ(0x7f040001u, *iter++);
+  ASSERT_EQ(0x7f040002u, *iter++);
+  ASSERT_EQ(0x7f040003u, *iter++);
+  ASSERT_EQ(0x7f040004u, *iter++);
+  ASSERT_EQ(0x7f040005u, *iter++);
+  ASSERT_EQ(0x7f040006u, *iter++);
+  ASSERT_EQ(0x7f040007u, *iter++);
+  ASSERT_EQ(0x7f040008u, *iter++);
+  ASSERT_EQ(0x7f040009u, *iter++);
+  ASSERT_EQ(0x7f04000au, *iter++);
+  ASSERT_EQ(0x7f04000bu, *iter++);
+  ASSERT_EQ(0x7f04000cu, *iter++);
+  ASSERT_EQ(0x7f04000du, *iter++);
+  ASSERT_EQ(0x7f050000u, *iter++);
+  ASSERT_EQ(0x7f050001u, *iter++);
+  ASSERT_EQ(0x7f060000u, *iter++);
+  ASSERT_EQ(0x7f070000u, *iter++);
+  ASSERT_EQ(0x7f070001u, *iter++);
+  ASSERT_EQ(0x7f070002u, *iter++);
+  ASSERT_EQ(0x7f070003u, *iter++);
+  ASSERT_EQ(end, iter);
+}
+
 }  // namespace android
diff --git a/libs/androidfw/tests/PosixUtils_test.cpp b/libs/androidfw/tests/PosixUtils_test.cpp
new file mode 100644
index 0000000..cf97f87
--- /dev/null
+++ b/libs/androidfw/tests/PosixUtils_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 <utility>
+
+#include "androidfw/PosixUtils.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace util {
+
+TEST(PosixUtilsTest, AbsolutePathToBinary) {
+  const auto result = ExecuteBinary({"/bin/date", "--help"});
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, 0);
+  ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, RelativePathToBinary) {
+  const auto result = ExecuteBinary({"date", "--help"});
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, 0);
+  ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, BadParameters) {
+  const auto result = ExecuteBinary({"/bin/date", "--this-parameter-is-not-supported"});
+  ASSERT_THAT(result, NotNull());
+  ASSERT_NE(result->status, 0);
+}
+
+TEST(PosixUtilsTest, NoSuchBinary) {
+  const auto result = ExecuteBinary({"/this/binary/does/not/exist"});
+  ASSERT_THAT(result, IsNull());
+}
+
+} // android
+} // util
diff --git a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
index bc742b0..df5f456 100644
--- a/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
+++ b/libs/hwui/tests/unit/SkiaBehaviorTests.cpp
@@ -35,23 +35,6 @@
     return bitmap;
 }
 
-/**
- * 1x1 bitmaps must not be optimized into solid color shaders, since HWUI can't
- * compose/render color shaders
- */
-TEST(SkiaBehavior, CreateBitmapShader1x1) {
-    SkBitmap origBitmap = createSkBitmap(1, 1);
-    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(origBitmap, kNever_SkCopyPixelsMode);
-    sk_sp<SkShader> s =
-            image->makeShader(SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode, nullptr);
-
-    SkBitmap bitmap;
-    SkShader::TileMode xy[2];
-    ASSERT_TRUE(s->isABitmap(&bitmap, nullptr, xy))
-            << "1x1 bitmap shader must query as bitmap shader";
-    EXPECT_EQ(origBitmap.pixelRef(), bitmap.pixelRef());
-}
-
 TEST(SkiaBehavior, genIds) {
     SkBitmap bitmap = createSkBitmap(100, 100);
     uint32_t genId = bitmap.getGenerationID();
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 6d10c2d..b1968ba 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2380,10 +2380,12 @@
     }
 
     /**
+     * Return the package that implements the {@link #NETWORK_PROVIDER} functionality.
+     *
      * @hide
      */
     @SystemApi
-    public String getNetworkProviderPackage() {
+    public @Nullable String getNetworkProviderPackage() {
         try {
             return mService.getNetworkProviderPackage();
         } catch (RemoteException e) {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 2395b24..b96a585 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -3252,7 +3252,7 @@
             int thumbnailLength = jpegInterchangeFormatLengthAttribute.getIntValue(mExifByteOrder);
 
             // The following code limits the size of thumbnail size not to overflow EXIF data area.
-            thumbnailLength = Math.min(thumbnailLength, in.available() - thumbnailOffset);
+            thumbnailLength = Math.min(thumbnailLength, in.getLength() - thumbnailOffset);
             if (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_RAF
                     || mMimeType == IMAGE_TYPE_RW2) {
                 thumbnailOffset += mExifOffset;
@@ -3981,6 +3981,10 @@
         public double readDouble() throws IOException {
             return Double.longBitsToDouble(readLong());
         }
+
+        public int getLength() {
+            return mLength;
+        }
     }
 
     // An output stream to write EXIF data area, which can be written in either little or big endian
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 0e5cbe4..5604ffd 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -3620,6 +3620,17 @@
                         && getState() == PLAYER_STATE_ERROR) {
                     status = CALL_STATUS_INVALID_OPERATION;
                 } else {
+                    if (mMediaCallType == CALL_COMPLETED_SEEK_TO) {
+                        synchronized (mTaskLock) {
+                            if (!mPendingTasks.isEmpty()) {
+                                Task nextTask = mPendingTasks.get(0);
+                                if (nextTask.mMediaCallType == mMediaCallType) {
+                                    throw new CommandSkippedException(
+                                            "consecutive seekTo is skipped except last one");
+                                }
+                            }
+                        }
+                    }
                     process();
                 }
             } catch (IllegalStateException e) {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index cdaabdc..d0ca04b 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -184,7 +184,6 @@
         if (shouldScan(mBluetoothFilters)) {
             final IntentFilter intentFilter = new IntentFilter();
             intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
-            intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
 
             mBluetoothBroadcastReceiver = new BluetoothBroadcastReceiver();
             registerReceiver(mBluetoothBroadcastReceiver, intentFilter);
diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk
index e645adc..03eb0d9 100644
--- a/packages/CtsShim/build/Android.mk
+++ b/packages/CtsShim/build/Android.mk
@@ -67,10 +67,6 @@
 LOCAL_JNI_SHARED_LIBRARIES := libshim_jni
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# out/target/common/obj/APPS/CtsShimPriv_intermediates/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
 
@@ -113,10 +109,6 @@
 LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/packages/CtsShim/build/shim/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
 
diff --git a/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
index 164fc5a..9855565 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
@@ -26,15 +26,16 @@
     private var _insets: WindowInsets? = null
 
     constructor(context: Context) : super(context) {
-        init(null, 0)
     }
 
     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
-        init(attrs, 0)
     }
 
-    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
-        init(attrs, defStyle)
+    constructor(
+        context: Context,
+        attrs: AttributeSet,
+        defStyle: Int
+    ) : super(context, attrs, defStyle) {
     }
 
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
@@ -81,8 +82,4 @@
             requestLayout()
         }
     }
-
-    private fun init(attrs: AttributeSet?, defStyle: Int) {
-    }
-
 }
diff --git a/packages/EasterEgg/src/com/android/egg/paint/Painting.kt b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
index a4a3d3d..fc7e8b0 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
@@ -17,7 +17,6 @@
 package com.android.egg.paint
 
 import android.content.Context
-import android.content.res.Resources
 import android.graphics.*
 import android.provider.Settings
 import android.util.AttributeSet
@@ -26,7 +25,6 @@
 import android.view.View
 import android.view.WindowInsets
 import java.util.concurrent.TimeUnit
-import android.util.Log
 import android.provider.Settings.System
 
 import org.json.JSONObject
@@ -86,11 +84,11 @@
         }
 
     var bitmap: Bitmap? = null
-    var paperColor : Int = 0xFFFFFFFF.toInt()
+    var paperColor: Int = 0xFFFFFFFF.toInt()
 
     private var _paintCanvas: Canvas? = null
     private val _bitmapLock = Object()
-    
+
     private var _drawPaint = Paint(Paint.ANTI_ALIAS_FLAG)
     private var _lastX = 0f
     private var _lastY = 0f
@@ -113,7 +111,9 @@
                         FADE_TO_BLACK_CF
 
                 synchronized(_bitmapLock) {
-                    c.drawBitmap(bitmap, 0f, 0f, pt)
+                    bitmap?.let {
+                        c.drawBitmap(bitmap!!, 0f, 0f, pt)
+                    }
                 }
                 invalidate()
             }
@@ -122,18 +122,22 @@
     }
 
     constructor(context: Context) : super(context) {
-        init(null, 0)
+        init()
     }
 
     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
-        init(attrs, 0)
+        init()
     }
 
-    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
-        init(attrs, defStyle)
+    constructor(
+        context: Context,
+        attrs: AttributeSet,
+        defStyle: Int
+    ) : super(context, attrs, defStyle) {
+        init()
     }
 
-    private fun init(attrs: AttributeSet?, defStyle: Int) {
+    private fun init() {
         loadDevicePressureData()
     }
 
@@ -264,7 +268,7 @@
         super.onDraw(canvas)
 
         bitmap?.let {
-            canvas.drawBitmap(bitmap, 0f, 0f, _drawPaint);
+            canvas.drawBitmap(bitmap!!, 0f, 0f, _drawPaint)
         }
     }
 
@@ -330,8 +334,8 @@
                 }
                 if (bits.width != oldBits.height || bits.height != oldBits.width) {
                     matrix.postScale(
-                            bits.width.toFloat()/oldBits.height,
-                            bits.height.toFloat()/oldBits.width)
+                            bits.width.toFloat() / oldBits.height,
+                            bits.height.toFloat() / oldBits.width)
                 }
                 c.matrix = matrix
             }
@@ -350,9 +354,10 @@
         val invertPaint = Paint()
         invertPaint.colorFilter = INVERT_CF
         synchronized(_bitmapLock) {
-            _paintCanvas?.drawBitmap(bitmap, 0f, 0f, invertPaint)
+            bitmap?.let {
+                _paintCanvas?.drawBitmap(bitmap!!, 0f, 0f, invertPaint)
+            }
         }
         invalidate()
     }
 }
-
diff --git a/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
index 86b11e7..460fa3a 100644
--- a/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
+++ b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
@@ -17,19 +17,10 @@
 package com.android.egg.paint
 
 import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.Paint
-import android.graphics.Rect
-import android.graphics.drawable.Drawable
-import android.text.TextPaint
-import android.transition.ChangeBounds
 import android.transition.Transition
 import android.transition.TransitionListenerAdapter
-import android.transition.TransitionManager
 import android.util.AttributeSet
 import android.view.*
-import android.view.animation.OvershootInterpolator
 import android.widget.FrameLayout
 
 class ToolbarView : FrameLayout {
@@ -44,15 +35,16 @@
     }
 
     constructor(context: Context) : super(context) {
-        init(null, 0)
     }
 
     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
-        init(attrs, 0)
     }
 
-    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
-        init(attrs, defStyle)
+    constructor(
+        context: Context,
+        attrs: AttributeSet,
+        defStyle: Int
+    ) : super(context, attrs, defStyle) {
     }
 
     override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets {
@@ -70,8 +62,4 @@
 
         return super.onApplyWindowInsets(insets)
     }
-
-    private fun init(attrs: AttributeSet?, defStyle: Int) {
-    }
-
 }
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 8c29a25..441dbac 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -16,7 +16,7 @@
 */
 package com.android.packageinstaller;
 
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -281,7 +281,7 @@
 
     @Override
     protected void onCreate(Bundle icicle) {
-        getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
         super.onCreate(null);
 
diff --git a/packages/PrintSpooler/Android.bp b/packages/PrintSpooler/Android.bp
new file mode 100644
index 0000000..c40a817
--- /dev/null
+++ b/packages/PrintSpooler/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_app {
+    name: "PrintSpooler",
+
+    resource_dirs: ["res"],
+
+    srcs: [
+        "src/**/*.java",
+        "src/com/android/printspooler/renderer/IPdfRenderer.aidl",
+        "src/com/android/printspooler/renderer/IPdfEditor.aidl",
+    ],
+
+    platform_apis: true,
+
+    jni_libs: ["libprintspooler_jni"],
+    static_libs: [
+        "android-support-v7-recyclerview",
+        "android-support-compat",
+        "android-support-media-compat",
+        "android-support-core-utils",
+        "android-support-core-ui",
+        "android-support-fragment",
+        "android-support-annotations",
+    ],
+}
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
deleted file mode 100644
index e356f38..0000000
--- a/packages/PrintSpooler/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += \
-    src/com/android/printspooler/renderer/IPdfRenderer.aidl \
-    src/com/android/printspooler/renderer/IPdfEditor.aidl
-
-LOCAL_PACKAGE_NAME := PrintSpooler
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
-LOCAL_STATIC_ANDROID_LIBRARIES := \
-    android-support-v7-recyclerview \
-    android-support-compat \
-    android-support-media-compat \
-    android-support-core-utils \
-    android-support-core-ui \
-    android-support-fragment
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android-support-annotations
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/Android.mk b/packages/PrintSpooler/tests/Android.mk
deleted file mode 100644
index 83e00ce..0000000
--- a/packages/PrintSpooler/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp
new file mode 100644
index 0000000..e88074e
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "PrintSpoolerOutOfProcessTests",
+
+    srcs: ["src/**/*.java"],
+
+    libs: ["android.test.runner.stubs"],
+    static_libs: [
+        "android-support-test",
+        "ub-uiautomator",
+        "mockito-target-minus-junit4",
+        "print-test-util-lib",
+    ],
+
+    sdk_version: "test_current",
+    test_suites: ["device-tests"],
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
deleted file mode 100644
index 161a600..0000000
--- a/packages/PrintSpooler/tests/outofprocess/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4 print-test-util-lib
-
-LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
index 7306d968..e407d72 100644
--- a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
@@ -187,17 +187,17 @@
 
         if (sendPackageName && includePackageName) {
             String[] packageNameKey =
-                    {resources.getString(android.R.string.config_help_package_name_key)};
+                    {resources.getString(android.R.string.config_helpPackageNameKey)};
             String[] packageNameValue =
-                    {resources.getString(android.R.string.config_help_package_name_value)};
+                    {resources.getString(android.R.string.config_helpPackageNameValue)};
             String helpIntentExtraKey =
-                    resources.getString(android.R.string.config_help_intent_extra_key);
+                    resources.getString(android.R.string.config_helpIntentExtraKey);
             String helpIntentNameKey =
-                    resources.getString(android.R.string.config_help_intent_name_key);
+                    resources.getString(android.R.string.config_helpIntentNameKey);
             String feedbackIntentExtraKey =
-                    resources.getString(android.R.string.config_feedback_intent_extra_key);
+                    resources.getString(android.R.string.config_feedbackIntentExtraKey);
             String feedbackIntentNameKey =
-                    resources.getString(android.R.string.config_feedback_intent_name_key);
+                    resources.getString(android.R.string.config_feedbackIntentNameKey);
             intent.putExtra(helpIntentExtraKey, packageNameKey);
             intent.putExtra(helpIntentNameKey, packageNameValue);
             intent.putExtra(feedbackIntentExtraKey, packageNameKey);
diff --git a/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
index 0f02abd..0748192 100644
--- a/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/res/layout/restricted_icon.xml
@@ -15,7 +15,7 @@
 -->
 <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/restricted_icon"
-    android:layout_width="@*android:dimen/config_restricted_icon_size"
-    android:layout_height="@*android:dimen/config_restricted_icon_size"
+    android:layout_width="@*android:dimen/config_restrictedIconSize"
+    android:layout_height="@*android:dimen/config_restrictedIconSize"
     android:tint="?android:attr/colorAccent"
     android:src="@*android:drawable/ic_info" />
diff --git a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
index b87c9e8..e278c10 100644
--- a/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/RestrictedLockUtils/src/com/android/settingslib/RestrictedLockUtils.java
@@ -91,13 +91,7 @@
 
     public static boolean isCurrentUserOrProfile(Context context, int userId) {
         UserManager um = context.getSystemService(UserManager.class);
-        int[] userIds = um.getProfileIds(UserHandle.myUserId(), true);
-        for (int i = 0; i < userIds.length; i++) {
-            if (userIds[i] == userId) {
-                return true;
-            }
-        }
-        return false;
+        return um.getUserProfiles().contains(UserHandle.of(userId));
     }
 
     public static class EnforcedAdmin {
diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
index c26295c..8bf8fce 100644
--- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
+++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/settingsspinner/SettingsSpinnerAdapter.java
@@ -24,7 +24,7 @@
 /**
  * An ArrayAdapter which was used by {@link SettingsSpinner} with settings style.
  */
-public class SettingsSpinnerAdapter<CharSequence> extends ArrayAdapter {
+public class SettingsSpinnerAdapter<T> extends ArrayAdapter<T> {
 
     /**
      * Constructs a new SettingsSpinnerAdapter with the given context.
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
index e1f6cdf..5dbcb79 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_widget.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
@@ -16,8 +16,8 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
     <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/restricted_icon"
-        android:layout_width="@*android:dimen/config_restricted_icon_size"
-        android:layout_height="@*android:dimen/config_restricted_icon_size"
+        android:layout_width="@*android:dimen/config_restrictedIconSize"
+        android:layout_height="@*android:dimen/config_restrictedIconSize"
         android:tint="?android:attr/colorAccent"
         android:src="@*android:drawable/ic_info"
         android:gravity="end|center_vertical" />
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index f57122e..1457fcf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -58,7 +58,7 @@
     public static Drawable getRestrictedPadlock(Context context) {
         Drawable restrictedPadlock = context.getDrawable(android.R.drawable.ic_info);
         final int iconSize = context.getResources().getDimensionPixelSize(
-                android.R.dimen.config_restricted_icon_size);
+                android.R.dimen.config_restrictedIconSize);
 
         TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
         int colorAccent = ta.getColor(0, 0);
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
index 3102239..3c45112 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
@@ -25,7 +25,6 @@
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.IconDrawableFactory;
 
 import com.android.settingslib.widget.CandidateInfo;
@@ -46,8 +45,8 @@
         this(context, pm, uid, cn, null /* summary */, true /* enabled */);
     }
 
-    public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info) {
-        this(context, pm, info, null /* summary */, true /* enabled */);
+    public DefaultAppInfo(Context context, PackageManager pm, int uid, PackageItemInfo info) {
+        this(context, pm, uid, info, null /* summary */, true /* enabled */);
     }
 
     public DefaultAppInfo(Context context, PackageManager pm, int uid, ComponentName cn,
@@ -61,12 +60,12 @@
         this.summary = summary;
     }
 
-    public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info,
+    public DefaultAppInfo(Context context, PackageManager pm, int uid, PackageItemInfo info,
                           String summary, boolean enabled) {
         super(enabled);
         mContext = context;
         mPm = pm;
-        userId = UserHandle.myUserId();
+        userId = uid;
         packageItemInfo = info;
         componentName = null;
         this.summary = summary;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4aca2bb..7124096 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -267,8 +267,10 @@
                 cachedDevice = mDeviceManager.addDevice(device);
                 Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
                         + cachedDevice);
-            } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
-                // Dispatch device add callback to show bonded BT device in discovery mode
+            } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
+                    &&!cachedDevice.getDevice().isConnected()) {
+                // Dispatch device add callback to show bonded but
+                // not connected devices in discovery mode
                 dispatchDeviceAdded(cachedDevice);
             }
             cachedDevice.setRssi(rssi);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 750a843..a2e30df 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -60,11 +60,11 @@
     private short mRssi;
 
     private final List<LocalBluetoothProfile> mProfiles =
-            new ArrayList<LocalBluetoothProfile>();
+            Collections.synchronizedList(new ArrayList<>());
 
     // List of profiles that were previously in mProfiles, but have been removed
     private final List<LocalBluetoothProfile> mRemovedProfiles =
-            new ArrayList<LocalBluetoothProfile>();
+            Collections.synchronizedList(new ArrayList<>());
 
     // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP
     private boolean mLocalNapRoleConnected;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
index 1091e16..36b70df 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
@@ -70,17 +70,17 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        when(mContext.getResources().getString(R.string.config_help_package_name_key))
+        when(mContext.getResources().getString(R.string.config_helpPackageNameKey))
                 .thenReturn(PACKAGE_NAME_KEY);
-        when(mContext.getResources().getString(R.string.config_help_package_name_value))
+        when(mContext.getResources().getString(R.string.config_helpPackageNameValue))
                 .thenReturn(PACKAGE_NAME_VALUE);
-        when(mContext.getResources().getString(R.string.config_help_intent_extra_key))
+        when(mContext.getResources().getString(R.string.config_helpIntentExtraKey))
                 .thenReturn(HELP_INTENT_EXTRA_KEY);
-        when(mContext.getResources().getString(R.string.config_help_intent_name_key))
+        when(mContext.getResources().getString(R.string.config_helpIntentNameKey))
                 .thenReturn(HELP_INTENT_NAME_KEY);
-        when(mContext.getResources().getString(R.string.config_feedback_intent_extra_key))
+        when(mContext.getResources().getString(R.string.config_feedbackIntentExtraKey))
                 .thenReturn(FEEDBACK_INTENT_EXTRA_KEY);
-        when(mContext.getResources().getString(R.string.config_feedback_intent_name_key))
+        when(mContext.getResources().getString(R.string.config_feedbackIntentNameKey))
                 .thenReturn(FEEDBACK_INTENT_NAME_KEY);
         when(mActivity.getPackageManager()).thenReturn(mPackageManager);
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
index 01f0d78..a92a2dd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
@@ -18,8 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -72,7 +72,7 @@
     @Test
     public void initInfoWithActivityInfo_shouldLoadInfo() {
         mPackageItemInfo.packageName = "test";
-        mInfo = new DefaultAppInfo(mContext, mPackageManager, mPackageItemInfo);
+        mInfo = new DefaultAppInfo(mContext, mPackageManager, 0 /* uid */, mPackageItemInfo);
         mInfo.loadLabel();
         Drawable icon = mInfo.loadIcon();
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index da1354b..8745a33 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -662,9 +662,6 @@
         dumpSetting(s, p,
                 Settings.Global.ANGLE_ENABLED_APP,
                 GlobalSettingsProto.Gpu.ANGLE_ENABLED_APP);
-        dumpSetting(s, p,
-                Settings.Global.GPU_DEBUG_LAYER_APP,
-                GlobalSettingsProto.Gpu.DEBUG_LAYER_APP);
         p.end(gpuToken);
 
         final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index ce503b3..822c39b 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -27,6 +27,7 @@
     <uses-permission android:name="android.permission.READ_SMS" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.READ_CALENDAR" />
@@ -55,6 +56,7 @@
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" />
     <!-- Development tool permissions granted to the shell. -->
     <uses-permission android:name="android.permission.SET_DEBUG_APP" />
     <uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
index 839b90b..ba4eb5f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
@@ -67,9 +67,25 @@
 
     class TriggerEvent {
         Sensor mSensor;
+        int mVendorType;
 
-        public TriggerEvent(Sensor sensor) {
+        /**
+         * Creates a trigger event
+         * @param sensor The type of sensor, e.g. TYPE_WAKE_LOCK_SCREEN
+         * @param vendorType The vendor type, which should be unique for each type of sensor,
+         *                   e.g. SINGLE_TAP = 1, DOUBLE_TAP = 2, etc.
+         */
+        public TriggerEvent(Sensor sensor, int vendorType) {
             mSensor = sensor;
+            mVendorType = vendorType;
+        }
+
+        public Sensor getSensor() {
+            return mSensor;
+        }
+
+        public int getVendorType() {
+            return mVendorType;
         }
     }
 }
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 7a38899..f138685 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -24,8 +24,7 @@
     android:clipChildren="false"
     android:clipToPadding="false"
     android:orientation="vertical"
-    android:background="@color/notification_guts_bg_color"
-    android:theme="@*android:style/Theme.DeviceDefault.Light">
+    android:background="@color/notification_guts_bg_color">
 
     <!-- Package Info -->
     <RelativeLayout
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index f0436de..d033057 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -49,11 +49,6 @@
         android:paddingEnd="@dimen/status_bar_padding_end"
         android:orientation="horizontal"
         >
-        <ViewStub
-            android:id="@+id/operator_name"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout="@layout/operator_name" />
         <FrameLayout
             android:layout_height="match_parent"
             android:layout_width="0dp"
@@ -70,6 +65,12 @@
                 android:layout_width="match_parent"
                 android:clipChildren="false"
             >
+                <ViewStub
+                    android:id="@+id/operator_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:layout="@layout/operator_name" />
+
                 <com.android.systemui.statusbar.policy.Clock
                     android:id="@+id/clock"
                     android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e1c71fa..42e19aa 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -761,6 +761,8 @@
     <string name="quick_settings_cast_device_default_description">Ready to cast</string>
     <!-- QuickSettings: Cast detail panel, text when there are no items [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cast_detail_empty_text">No devices available</string>
+    <!-- QuickSettings: Cast unavailable, text when not connected to WiFi [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_cast_no_wifi">Wi\u2011Fi not connected</string>
     <!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
     <string name="quick_settings_brightness_dialog_title">Brightness</string>
     <!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
@@ -1999,6 +2001,9 @@
     <!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_open_details">Open details.</string>
 
+    <!-- accessibility label for quick settings items that are currently disabled. Must have a reason [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_not_available">Unvailable due to <xliff:g name="reason" id="reason" example="Wifi not available">%s</xliff:g></string>
+
     <!-- accessibility label for quick settings items that open a details page [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_open_settings">Open <xliff:g name="page" example="Bluetooth">%s</xliff:g> settings.</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 4d24d82..3007b6e 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -736,14 +736,19 @@
             switch (gravity) {
                 case Gravity.TOP:
                     out.set(displayCutout.getBoundingRectTop());
+                    break;
                 case Gravity.LEFT:
                     out.set(displayCutout.getBoundingRectLeft());
+                    break;
                 case Gravity.BOTTOM:
                     out.set(displayCutout.getBoundingRectBottom());
+                    break;
                 case Gravity.RIGHT:
                     out.set(displayCutout.getBoundingRectRight());
+                    break;
+                default:
+                    out.setEmpty();
             }
-            out.setEmpty();
         }
 
         private void localBounds(Rect out) {
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 6d79066..449ed8c 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -14,7 +14,7 @@
 
 package com.android.systemui;
 
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -69,7 +69,7 @@
                     .setPositiveButton(R.string.slice_permission_allow, this)
                     .setOnDismissListener(this)
                     .create();
-            dialog.getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+            dialog.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
             dialog.show();
             TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1);
             t1.setText(getString(R.string.slice_permission_text_1, app2));
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 43dd412..77f7ad4f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -423,7 +423,7 @@
     }
 
     /**
-     * A Sensor that is injected via plugin, for better ContextHub interface.
+     * A Sensor that is injected via plugin.
      */
     private class PluginTriggerSensor extends TriggerSensor {
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 4a67868..df76315 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.media;
 
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -151,7 +151,7 @@
         ((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this);
         final Window w = mDialog.getWindow();
         w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        w.addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
         mDialog.show();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index ed78048..921db69 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -46,6 +46,7 @@
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
 
 import java.util.LinkedHashMap;
 import java.util.Set;
@@ -58,16 +59,18 @@
     private final CastController mController;
     private final CastDetailAdapter mDetailAdapter;
     private final KeyguardMonitor mKeyguard;
+    private final NetworkController mNetworkController;
     private final Callback mCallback = new Callback();
     private final ActivityStarter mActivityStarter;
     private Dialog mDialog;
-    private boolean mRegistered;
+    private boolean mWifiConnected;
 
     public CastTile(QSHost host) {
         super(host);
         mController = Dependency.get(CastController.class);
         mDetailAdapter = new CastDetailAdapter();
         mKeyguard = Dependency.get(KeyguardMonitor.class);
+        mNetworkController = Dependency.get(NetworkController.class);
         mActivityStarter = Dependency.get(ActivityStarter.class);
     }
 
@@ -87,10 +90,12 @@
         if (listening) {
             mController.addCallback(mCallback);
             mKeyguard.addCallback(mCallback);
+            mNetworkController.addCallback(mSignalCallback);
         } else {
             mController.setDiscovering(false);
             mController.removeCallback(mCallback);
             mKeyguard.removeCallback(mCallback);
+            mNetworkController.removeCallback(mSignalCallback);
         }
     }
 
@@ -112,6 +117,9 @@
 
     @Override
     protected void handleClick() {
+        if (getState().state == Tile.STATE_UNAVAILABLE) {
+            return;
+        }
         if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
             mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
                 showDetail(true);
@@ -164,13 +172,22 @@
         if (!state.value && connecting) {
             state.label = mContext.getString(R.string.quick_settings_connecting);
         }
-        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
                 : R.drawable.ic_qs_cast_off);
+        if (mWifiConnected) {
+            state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+            state.secondaryLabel = "";
+            state.contentDescription = state.contentDescription + ","
+                    + mContext.getString(R.string.accessibility_quick_settings_open_details);
+            state.expandedAccessibilityClassName = Button.class.getName();
+        } else {
+            state.state = Tile.STATE_UNAVAILABLE;
+            String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi);
+            state.secondaryLabel = noWifi;
+            state.contentDescription = state.contentDescription + ", " + mContext.getString(
+                    R.string.accessibility_quick_settings_not_available, noWifi);
+        }
         mDetailAdapter.updateItems(devices);
-        state.expandedAccessibilityClassName = Button.class.getName();
-        state.contentDescription = state.contentDescription + ","
-                + mContext.getString(R.string.accessibility_quick_settings_open_details);
     }
 
     @Override
@@ -192,6 +209,22 @@
                 : mContext.getString(R.string.quick_settings_cast_device_default_name);
     }
 
+    private final NetworkController.SignalCallback mSignalCallback =
+            new NetworkController.SignalCallback() {
+                @Override
+                public void setWifiIndicators(boolean enabled,
+                        NetworkController.IconState statusIcon,
+                        NetworkController.IconState qsIcon, boolean activityIn, boolean activityOut,
+                        String description, boolean isTransient, String statusLabel) {
+                    // statusIcon.visible has the connected status information
+                    boolean enabledAndConnected = enabled && qsIcon.visible;
+                    if (enabledAndConnected != mWifiConnected) {
+                        mWifiConnected = enabledAndConnected;
+                        refreshState();
+                    }
+                }
+            };
+
     private final class Callback implements CastController.Callback, KeyguardMonitor.Callback {
         @Override
         public void onCastDevicesChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 0c5f391..a00eac4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -19,14 +19,14 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.admin.DevicePolicyManager;
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Resources;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Color;
+import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.BatteryManager;
@@ -106,6 +106,7 @@
 
     private final DevicePolicyManager mDevicePolicyManager;
     private boolean mDozing;
+    private float mDarkAmount;
 
     /**
      * Creates a new KeyguardIndicationController and registers callbacks.
@@ -298,6 +299,15 @@
         if (mVisible) {
             // Walk down a precedence-ordered list of what indication
             // should be shown based on user or device state
+            if (mDozing) {
+                if (!TextUtils.isEmpty(mTransientIndication)) {
+                    mTextView.setTextColor(Color.WHITE);
+                    mTextView.switchIndication(mTransientIndication);
+                }
+                updateAlphas();
+                return;
+            }
+
             KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
             int userId = KeyguardUpdateMonitor.getCurrentUser();
             String trustGrantedIndication = getTrustGrantedIndication();
@@ -335,6 +345,14 @@
         }
     }
 
+    private void updateAlphas() {
+        if (!TextUtils.isEmpty(mTransientIndication)) {
+            mTextView.setAlpha(1f);
+        } else {
+            mTextView.setAlpha(1f - mDarkAmount);
+        }
+    }
+
     // animates textView - textView moves up and bounces down
     private void animateText(KeyguardIndicationTextView textView, String indication) {
         int yTranslation = mContext.getResources().getInteger(
@@ -492,6 +510,14 @@
         pw.println("  computePowerIndication(): " + computePowerIndication());
     }
 
+    public void setDarkAmount(float darkAmount) {
+        if (mDarkAmount == darkAmount) {
+            return;
+        }
+        mDarkAmount = darkAmount;
+        updateAlphas();
+    }
+
     protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
         public static final int HIDE_DELAY_MS = 5000;
         private int mLastSuccessiveErrorMessage = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index d6719f0..78a5817 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -22,6 +22,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.statusbar.phone.StatusBar;
 import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -39,6 +40,7 @@
             = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
 
     private final ArrayList<RankedListener> mListeners = new ArrayList<>();
+    private boolean mIsDozing;
     private int mState;
     private int mLastState;
     private boolean mLeaveOpenOnKeyguardHide;
@@ -57,6 +59,11 @@
         return mState;
     }
 
+    /**
+     * Update the status bar state
+     * @param state see {@link StatusBarState} for valid options
+     * @return {@code true} if the state changed, else {@code false}
+     */
     public boolean setState(int state) {
         if (state > MAX_STATE || state < MIN_STATE) {
             throw new IllegalArgumentException("Invalid state " + state);
@@ -82,6 +89,32 @@
         return true;
     }
 
+    public boolean isDozing() {
+        return mIsDozing;
+    }
+
+    /**
+     * Update the dozing state from {@link StatusBar}'s perspective
+     * @param isDozing well, are we dozing?
+     * @return {@code true} if the state changed, else {@code false}
+     */
+    @SuppressWarnings("UnusedReturnValue")
+    public boolean setIsDozing(boolean isDozing) {
+        if (mIsDozing == isDozing) {
+            return false;
+        }
+
+        mIsDozing = isDozing;
+
+        synchronized (mListeners) {
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onDozingChanged(isDozing);
+            }
+        }
+
+        return true;
+    }
+
     public boolean goingToFullShade() {
         return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
     }
@@ -144,16 +177,6 @@
         return StatusBarState.toShortString(state);
     }
 
-    public interface StateListener {
-        public default void onStatePreChange(int oldState, int newState) {
-        }
-
-        public default void onStatePostChange() {
-        }
-
-        public void onStateChanged(int newState);
-    }
-
     private class RankedListener {
         private final StateListener listener;
         private final int rank;
@@ -163,4 +186,40 @@
             rank = r;
         }
     }
+
+    /**
+     * Listener for StatusBarState updates
+     */
+    public interface StateListener {
+
+        /**
+         * Callback before the new state is applied, for those who need to preempt the change
+         * @param oldState state before the change
+         * @param newState new state to be applied in {@link #onStateChanged}
+         */
+        public default void onStatePreChange(int oldState, int newState) {
+        }
+
+        /**
+         * Callback after all listeners have had a chance to update based on the state change
+         */
+        public default void onStatePostChange() {
+        }
+
+        /**
+         * Required callback. Get the new state and do what you will with it. Keep in mind that
+         * other listeners are typically unordered and don't rely on your work being done before
+         * other peers
+         *
+         * Only called if the state is actually different
+         * @param newState the new {@link StatusBarState}
+         */
+        public void onStateChanged(int newState);
+
+        /**
+         * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+         * @param isDozing {@code true} if dozing according to {@link StatusBar}
+         */
+        public default void onDozingChanged(boolean isDozing) {}
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 2450e44..24665ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -491,6 +491,10 @@
     @Override
     public void onStateChanged(int newState) {
         super.onStateChanged(newState);
+        if (mFullscreenUserSwitcher == null) {
+            return; // Not using the full screen user switcher.
+        }
+
         if (newState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
             if (!mFullscreenUserSwitcher.isVisible()) {
                 // Current execution path continues to set state after this, thus we deffer the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 2ca7282..f76284d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.view.NotificationHeaderView;
@@ -76,8 +77,11 @@
         }
         Drawable background = mView.getBackground();
         if (background instanceof ColorDrawable) {
-            mBackgroundColor = ((ColorDrawable) background).getColor();
-            mView.setBackground(null);
+            int backgroundColor = ((ColorDrawable) background).getColor();
+            if (backgroundColor != Color.TRANSPARENT) {
+                mBackgroundColor = backgroundColor;
+                mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 9acaf21..c66bbb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -48,6 +48,7 @@
     private final NotificationStackScrollLayout mStackScroller;
     private final HeadsUpStatusBarView mHeadsUpStatusBarView;
     private final View mClockView;
+    private final View mOperatorNameView;
     private final DarkIconDispatcher mDarkIconDispatcher;
     private final NotificationPanelView mPanelView;
     private final Consumer<ExpandableNotificationRow>
@@ -65,8 +66,10 @@
     private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
             (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
                     -> updatePanelTranslation();
+    private boolean mAnimationsEnabled = true;
     Point mPoint;
 
+
     public HeadsUpAppearanceController(
             NotificationIconAreaController notificationIconAreaController,
             HeadsUpManagerPhone headsUpManager,
@@ -75,7 +78,8 @@
                 statusbarView.findViewById(R.id.heads_up_status_bar_view),
                 statusbarView.findViewById(R.id.notification_stack_scroller),
                 statusbarView.findViewById(R.id.notification_panel),
-                statusbarView.findViewById(R.id.clock));
+                statusbarView.findViewById(R.id.clock),
+                statusbarView.findViewById(R.id.operator_name_frame));
     }
 
     @VisibleForTesting
@@ -85,7 +89,8 @@
             HeadsUpStatusBarView headsUpStatusBarView,
             NotificationStackScrollLayout stackScroller,
             NotificationPanelView panelView,
-            View clockView) {
+            View clockView,
+            View operatorNameView) {
         mNotificationIconAreaController = notificationIconAreaController;
         mHeadsUpManager = headsUpManager;
         mHeadsUpManager.addListener(this);
@@ -101,6 +106,7 @@
         mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
         mStackScroller.setHeadsUpAppearanceController(this);
         mClockView = clockView;
+        mOperatorNameView = operatorNameView;
         mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
         mDarkIconDispatcher.addDarkReceiver(this);
 
@@ -230,20 +236,52 @@
             mShown = isShown;
             if (isShown) {
                 mHeadsUpStatusBarView.setVisibility(View.VISIBLE);
-                CrossFadeHelper.fadeIn(mHeadsUpStatusBarView, CONTENT_FADE_DURATION /* duration */,
-                        CONTENT_FADE_DELAY /* delay */);
-                CrossFadeHelper.fadeOut(mClockView, CONTENT_FADE_DURATION/* duration */,
-                        0 /* delay */, () -> mClockView.setVisibility(View.INVISIBLE));
+                show(mHeadsUpStatusBarView);
+                hide(mClockView, View.INVISIBLE);
+                if (mOperatorNameView != null) {
+                    hide(mOperatorNameView, View.INVISIBLE);
+                }
             } else {
-                CrossFadeHelper.fadeIn(mClockView, CONTENT_FADE_DURATION /* duration */,
-                        CONTENT_FADE_DELAY /* delay */);
-                CrossFadeHelper.fadeOut(mHeadsUpStatusBarView, CONTENT_FADE_DURATION/* duration */,
-                        0 /* delay */, () -> mHeadsUpStatusBarView.setVisibility(View.GONE));
-
+                show(mClockView);
+                if (mOperatorNameView != null) {
+                    show(mOperatorNameView);
+                }
+                hide(mHeadsUpStatusBarView, View.GONE);
             }
         }
     }
 
+    /**
+     * Hides the view and sets the state to endState when finished.
+     *
+     * @param view The view to hide.
+     * @param endState One of {@link View#INVISIBLE} or {@link View#GONE}.
+     * @see View#setVisibility(int)
+     *
+     */
+    private void hide(View view, int endState) {
+        if (mAnimationsEnabled) {
+            CrossFadeHelper.fadeOut(view, CONTENT_FADE_DURATION /* duration */,
+                    0 /* delay */, () -> view.setVisibility(endState));
+        } else {
+            view.setVisibility(endState);
+        }
+    }
+
+    private void show(View view) {
+        if (mAnimationsEnabled) {
+            CrossFadeHelper.fadeIn(view, CONTENT_FADE_DURATION /* duration */,
+                    CONTENT_FADE_DELAY /* delay */);
+        } else {
+            view.setVisibility(View.VISIBLE);
+        }
+    }
+
+    @VisibleForTesting
+    void setAnimationsEnabled(boolean enabled) {
+        mAnimationsEnabled = enabled;
+    }
+
     @VisibleForTesting
     public boolean isShown() {
         return mShown;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index ae1353d..072343a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -560,7 +560,7 @@
             return;
         }
         mDarkAmount = darkAmount;
-        mIndicationArea.setAlpha(1f - darkAmount);
+        mIndicationController.setDarkAmount(darkAmount);
         mLockIcon.setDarkAmount(darkAmount);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 2a4595b..8ac8677 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -361,6 +361,8 @@
         } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
             onFullyHidden();
             mExpansionCallback.onFullyHidden();
+        } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
+            mExpansionCallback.onStartingToHide();
         }
     }
 
@@ -481,6 +483,7 @@
 
     public interface BouncerExpansionCallback {
         void onFullyShown();
+        void onStartingToHide();
         void onFullyHidden();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7c84df9..e85ff8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -519,7 +519,14 @@
         mStatusIconContainer.setAlpha(alpha);
         mStatusIconContainer.setVisibility(visibility);
 
-        mSystemIconsContainer.setTranslationX(-mCurrentBurnInOffsetX * mDarkAmount);
+        float iconsX = -mCurrentBurnInOffsetX;
+        if (mMultiUserSwitch.getVisibility() == VISIBLE) {
+            // Squared alpha to add a nice easing curve and avoid overlap during animation.
+            mMultiUserAvatar.setAlpha(alpha * alpha);
+            iconsX += mMultiUserAvatar.getPaddingLeft() + mMultiUserAvatar.getWidth()
+                    + mMultiUserAvatar.getPaddingRight();
+        }
+        mSystemIconsContainer.setTranslationX(iconsX * mDarkAmount);
         mSystemIconsContainer.setTranslationY(mCurrentBurnInOffsetY * mDarkAmount);
         updateIconsAndTextColors();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c4efa94..980ba87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -1100,10 +1100,11 @@
                         visibilityToString(getCurrentView().getVisibility()),
                         getCurrentView().getAlpha()));
 
-        pw.println(String.format("      disabled=0x%08x vertical=%s menu=%s",
+        pw.println(String.format("      disabled=0x%08x vertical=%s menu=%s darkIntensity=%.2f",
                         mDisabledFlags,
                         mVertical ? "true" : "false",
-                        getMenuButton().isVisible() ? "true" : "false"));
+                        getMenuButton().isVisible() ? "true" : "false",
+                        getLightTransitionsController().getCurrentDarkIntensity()));
 
         dumpButton(pw, "back", getBackButton());
         dumpButton(pw, "home", getHomeButton());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 56bef2e..3bdd601 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3756,9 +3756,6 @@
         Trace.beginSection("StatusBar#updateKeyguardState");
         if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationController.setVisible(true);
-            boolean dozingAnimated = mDozingRequested
-                    && DozeParameters.getInstance(mContext).shouldControlScreenOff();
-            mNotificationPanel.resetViews(dozingAnimated);
             if (mKeyguardUserSwitcher != null) {
                 mKeyguardUserSwitcher.setKeyguard(true,
                         mStatusBarStateController.fromShadeLocked());
@@ -3790,6 +3787,47 @@
     }
 
     @Override
+    public void onDozingChanged(boolean isDozing) {
+        Trace.beginSection("StatusBar#updateDozing");
+        mDozing = isDozing;
+
+        // Collapse the notification panel if open
+        boolean dozingAnimated = mDozingRequested
+                && DozeParameters.getInstance(mContext).shouldControlScreenOff();
+        mNotificationPanel.resetViews(dozingAnimated);
+
+        mKeyguardViewMediator.setAodShowing(mDozing);
+
+        //TODO: make these folks listeners of StatusBarStateController.onDozingChanged
+        mStatusBarWindowController.setDozing(mDozing);
+        mStatusBarKeyguardViewManager.setDozing(mDozing);
+        if (mAmbientIndicationContainer instanceof DozeReceiver) {
+            ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
+        }
+
+        mEntryManager.updateNotifications();
+        updateDozingState();
+        updateScrimController();
+        updateReportRejectedTouchVisibility();
+        Trace.endSection();
+    }
+
+    private void updateDozing() {
+        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
+        boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
+                || mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+        // When in wake-and-unlock we may not have received a change to mState
+        // but we still should not be dozing, manually set to false.
+        if (mBiometricUnlockController.getMode() ==
+                BiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
+            dozing = false;
+        }
+
+        mStatusBarStateController.setIsDozing(dozing);
+    }
+
+    @Override
     public void onActivationReset(ActivatableNotificationView view) {
         if (view == mNotificationPanel.getActivatedChild()) {
             mNotificationPanel.setActivatedChild(null);
@@ -4341,34 +4379,6 @@
         updateScrimController();
     }
 
-    private void updateDozing() {
-        Trace.beginSection("StatusBar#updateDozing");
-        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
-        boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
-                || mBiometricUnlockController.getMode()
-                        == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
-        // When in wake-and-unlock we may not have received a change to mState
-        // but we still should not be dozing, manually set to false.
-        if (mBiometricUnlockController.getMode() ==
-                mBiometricUnlockController.MODE_WAKE_AND_UNLOCK) {
-            dozing = false;
-        }
-        if (mDozing != dozing) {
-            mDozing = dozing;
-            mKeyguardViewMediator.setAodShowing(mDozing);
-            mStatusBarWindowController.setDozing(mDozing);
-            mStatusBarKeyguardViewManager.setDozing(mDozing);
-            if (mAmbientIndicationContainer instanceof DozeReceiver) {
-                ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
-            }
-            mEntryManager.updateNotifications();
-            updateDozingState();
-            updateScrimController();
-            updateReportRejectedTouchVisibility();
-        }
-        Trace.endSection();
-    }
-
     @VisibleForTesting
     void updateScrimController() {
         Trace.beginSection("StatusBar#updateScrimController");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 3db1456..ac3608b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -84,6 +84,11 @@
         }
 
         @Override
+        public void onStartingToHide() {
+            updateStates();
+        }
+
+        @Override
         public void onFullyHidden() {
             updateStates();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 57c7e28..0d37b55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -173,9 +173,9 @@
         }
 
         if (state.dozing) {
-            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+            mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         } else {
-            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+            mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
index af99236..e85dee8 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
@@ -51,7 +51,9 @@
     public void onTuningChanged(String key, String newValue) {
         int dimen = mDefaultSize;
         if (newValue != null) {
-            dimen = (int) (Integer.parseInt(newValue) * mDensity);
+            try {
+                dimen = (int) (Integer.parseInt(newValue) * mDensity);
+            } catch (NumberFormatException ex) {}
         }
         int left = mView.isLayoutRtl() ? FLAG_END : FLAG_START;
         int right = mView.isLayoutRtl() ? FLAG_START : FLAG_END;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 66d5ee1..4102e63 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -54,7 +54,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         Window window = getWindow();
-        window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        window.addSystemFlags(WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
         window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
 
         super.onCreate(icicle);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
new file mode 100644
index 0000000..d9412ec
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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 com.android.systemui.qs.tiles;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.service.quicksettings.Tile;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class CastTileTest extends SysuiTestCase {
+
+    @Mock
+    private CastController mController;
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
+    private KeyguardMonitor mKeyguard;
+    @Mock
+    private NetworkController mNetworkController;
+    @Mock
+    private QSTileHost mHost;
+    @Mock
+    NetworkController.SignalCallback mCallback;
+
+    private TestableLooper mTestableLooper;
+    private CastTile mCastTile;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mTestableLooper = TestableLooper.get(this);
+
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+        mController = mDependency.injectMockDependency(CastController.class);
+        mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class);
+        mKeyguard = mDependency.injectMockDependency(KeyguardMonitor.class);
+        mNetworkController = mDependency.injectMockDependency(NetworkController.class);
+
+        when(mHost.getContext()).thenReturn(mContext);
+
+        mCastTile = new CastTile(mHost);
+
+        // We are not setting the mocks to listening, so we trigger a first refresh state to
+        // set the initial state
+        mCastTile.refreshState();
+
+        mCastTile.handleSetListening(true);
+        ArgumentCaptor<NetworkController.SignalCallback> signalCallbackArgumentCaptor =
+                ArgumentCaptor.forClass(NetworkController.SignalCallback.class);
+        verify(mNetworkController).addCallback(signalCallbackArgumentCaptor.capture());
+        mCallback = signalCallbackArgumentCaptor.getValue();
+
+    }
+
+    @Test
+    public void testStateUnavailable_wifiDisabled() {
+        NetworkController.IconState qsIcon =
+                new NetworkController.IconState(false, 0, "");
+        mCallback.setWifiIndicators(false, mock(NetworkController.IconState.class),
+                qsIcon, false,false, "",
+                false, "");
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
+    }
+
+    @Test
+    public void testStateUnavailable_wifiNotConnected() {
+        NetworkController.IconState qsIcon =
+                new NetworkController.IconState(false, 0, "");
+        mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+                qsIcon, false,false, "",
+                false, "");
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_UNAVAILABLE, mCastTile.getState().state);
+    }
+
+    @Test
+    public void testStateActive_wifiEnabledAndCasting() {
+        CastController.CastDevice device = mock(CastController.CastDevice.class);
+        device.state = CastController.CastDevice.STATE_CONNECTED;
+        Set<CastController.CastDevice> devices = new HashSet<>();
+        devices.add(device);
+        when(mController.getCastDevices()).thenReturn(devices);
+
+        NetworkController.IconState qsIcon =
+                new NetworkController.IconState(true, 0, "");
+        mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+                qsIcon, false,false, "",
+                false, "");
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state);
+    }
+
+    @Test
+    public void testStateInactive_wifiEnabledNotCasting() {
+        NetworkController.IconState qsIcon =
+                new NetworkController.IconState(true, 0, "");
+        mCallback.setWifiIndicators(true, mock(NetworkController.IconState.class),
+                qsIcon, false,false, "",
+                false, "");
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_INACTIVE, mCastTile.getState().state);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index bdd05c7..aae6d93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -28,6 +30,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.Context;
+import android.graphics.Color;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
@@ -45,6 +48,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -54,9 +59,13 @@
 
     private String mDisclosureWithOrganization;
 
-    private DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
-    private ViewGroup mIndicationArea = mock(ViewGroup.class);
-    private KeyguardIndicationTextView mDisclosure = mock(KeyguardIndicationTextView.class);
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private ViewGroup mIndicationArea;
+    @Mock
+    private KeyguardIndicationTextView mDisclosure;
+    private KeyguardIndicationTextView mTextView;
 
     private KeyguardIndicationController mController;
     private WakeLockFake mWakeLock;
@@ -64,7 +73,9 @@
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        mTextView = new KeyguardIndicationTextView(mContext);
 
         mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
         mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
@@ -74,6 +85,7 @@
 
         when(mIndicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure))
                 .thenReturn(mDisclosure);
+        when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
 
         mWakeLock = new WakeLockFake();
     }
@@ -189,4 +201,17 @@
         });
         assertFalse("WakeLock expected: RELEASED, was: HELD", held[0]);
     }
+
+    @Test
+    public void transientIndication_visibleWhenDozing() {
+        createController();
+
+        mController.setVisible(true);
+        mController.showTransientIndication("Test");
+        mController.setDozing(true);
+
+        assertThat(mTextView.getText()).isEqualTo("Test");
+        assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
+        assertThat(mTextView.getAlpha()).isEqualTo(1f);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index a4004ae..10b0d83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -54,6 +54,7 @@
     private ExpandableNotificationRow mFirst;
     private HeadsUpStatusBarView mHeadsUpStatusBarView;
     private HeadsUpManagerPhone mHeadsUpManager;
+    private View mOperatorNameView;
 
     @Before
     public void setUp() throws Exception {
@@ -63,13 +64,15 @@
         mHeadsUpStatusBarView = new HeadsUpStatusBarView(mContext, mock(View.class),
                 mock(TextView.class));
         mHeadsUpManager = mock(HeadsUpManagerPhone.class);
+        mOperatorNameView = new View(mContext);
         mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                 mock(NotificationIconAreaController.class),
                 mHeadsUpManager,
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
-                new View(mContext));
+                new View(mContext),
+                mOperatorNameView);
         mHeadsUpAppearanceController.setExpandedHeight(0.0f, 0.0f);
     }
 
@@ -116,6 +119,22 @@
     }
 
     @Test
+    public void testOperatorNameViewUpdated() {
+        mHeadsUpAppearanceController.setAnimationsEnabled(false);
+
+        mFirst.setPinned(true);
+        when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
+        when(mHeadsUpManager.getTopEntry()).thenReturn(mFirst.getEntry());
+        mHeadsUpAppearanceController.onHeadsUpPinned(mFirst);
+        Assert.assertEquals(View.INVISIBLE, mOperatorNameView.getVisibility());
+
+        mFirst.setPinned(false);
+        when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
+        mHeadsUpAppearanceController.onHeadsUpUnPinned(mFirst);
+        Assert.assertEquals(View.VISIBLE, mOperatorNameView.getVisibility());
+    }
+
+    @Test
     public void testHeaderReadFromOldController() {
         mHeadsUpAppearanceController.setExpandedHeight(1.0f, 1.0f);
 
@@ -125,6 +144,7 @@
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
+                new View(mContext),
                 new View(mContext));
         newController.readFrom(mHeadsUpAppearanceController);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index a7954f2..020682b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -170,13 +170,17 @@
         mBouncer.ensureView();
         mBouncer.setExpansion(0.5f);
 
-        mBouncer.setExpansion(1);
+        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
         verify(mFalsingManager).onBouncerHidden();
         verify(mExpansionCallback).onFullyHidden();
 
-        mBouncer.setExpansion(0);
+        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
         verify(mFalsingManager).onBouncerShown();
         verify(mExpansionCallback).onFullyShown();
+
+        verify(mExpansionCallback, never()).onStartingToHide();
+        mBouncer.setExpansion(0.9f);
+        verify(mExpansionCallback).onStartingToHide();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index f7a7e04..de26c70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -74,14 +74,14 @@
                 ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
         verify(mWindowManager).updateViewLayout(any(), captor.capture());
         int flag = captor.getValue().privateFlags
-                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         assertThat(flag).isNotEqualTo(0);
 
         reset(mWindowManager);
         mStatusBarWindowController.setDozing(false);
         verify(mWindowManager).updateViewLayout(any(), captor.capture());
         flag = captor.getValue().privateFlags
-                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+                & WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
         assertThat(flag).isEqualTo(0);
     }
 
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 5e87707..d86de5d 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6549,6 +6549,21 @@
     // Subtype: The importance of a notification has been changed
     ADJUSTMENT_KEY_IMPORTANCE = 1580;
 
+    // OPEN: Settings > Network & internet > Mobile network > Choose network
+    // CATEGORY: SETTINGS
+    // OS: Q
+    MOBILE_NETWORK_SELECT = 1581;
+
+    // OPEN: Settings > Network & internet > Mobile network > Mobile Data > Dialog
+    // CATEGORY: SETTINGS
+    // OS: Q
+    MOBILE_DATA_DIALOG = 1582;
+
+    // OPEN: Settings > Network & internet > Mobile network > Data roaming > Dialog
+    // CATEGORY: SETTINGS
+    // OS: Q
+    MOBILE_ROAMING_DIALOG = 1583;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index da52d40..39866a7 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -56,6 +56,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -629,10 +630,10 @@
                     onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent(
                             providerUserId, true);
                 } else {
-                    final String dialogMessage = mPackageManagerInternal.getSuspendedDialogMessage(
-                            providerPackage, providerUserId);
+                    final SuspendDialogInfo dialogInfo = mPackageManagerInternal
+                            .getSuspendedDialogInfo(providerPackage, providerUserId);
                     onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
-                            providerPackage, suspendingPackage, dialogMessage, providerUserId);
+                            providerPackage, suspendingPackage, dialogInfo, providerUserId);
                 }
             } else if (provider.maskedByQuietProfile) {
                 showBadge = true;
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 6904b3f..3a5232a 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -708,8 +708,6 @@
             } else {
                 throw TaskException.create();
             }
-        } finally {
-            mBlankStateFile.delete();
         }
         checkAgentResult(packageInfo, agentResult);
     }
@@ -1037,8 +1035,13 @@
 
     private void cleanUpAgent(@StateTransaction int stateTransaction) {
         applyStateTransaction(stateTransaction);
-        mBackupDataFile.delete();
+        if (mBackupDataFile != null) {
+            mBackupDataFile.delete();
+        }
         mBlankStateFile.delete();
+        mSavedStateFile = null;
+        mBackupDataFile = null;
+        mNewStateFile = null;
         tryCloseFileDescriptor(mSavedState, "old state");
         tryCloseFileDescriptor(mBackupData, "backup data");
         tryCloseFileDescriptor(mNewState, "new state");
@@ -1059,7 +1062,9 @@
                 mNewStateFile.renameTo(mSavedStateFile);
                 break;
             case StateTransaction.DISCARD_NEW:
-                mNewStateFile.delete();
+                if (mNewStateFile != null) {
+                    mNewStateFile.delete();
+                }
                 break;
             case StateTransaction.DISCARD_ALL:
                 mSavedStateFile.delete();
diff --git a/services/core/Android.bp b/services/core/Android.bp
index d9519e0..2fa2941 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -4,6 +4,7 @@
     aidl: {
         include_dirs: [
             "frameworks/native/aidl/binder",
+            "frameworks/native/cmds/dumpstate/binder",
             "system/core/storaged/binder",
             "system/netd/server/binder",
             "system/vold/binder",
@@ -11,6 +12,7 @@
     },
     srcs: [
         "java/**/*.java",
+        ":dumpstate_aidl",
         ":netd_aidl",
         ":netd_metrics_aidl",
         ":installd_aidl",
@@ -44,6 +46,7 @@
         "android.hardware.configstore-V1.0-java",
         "android.hardware.contexthub-V1.0-java",
         "android.hidl.manager-V1.0-java",
+        "netd_aidl_interface-java",
     ],
 }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5e8ffb7..bc6254a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1679,6 +1679,16 @@
                 "ConnectivityService");
     }
 
+    private void enforceAnyPermissionOf(String... permissions) {
+        for (String permission : permissions) {
+            if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
+                return;
+            }
+        }
+        throw new SecurityException(
+            "Requires one of the following permissions: " + String.join(", ", permissions) + ".");
+    }
+
     private void enforceInternetPermission() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.INTERNET,
@@ -1723,6 +1733,13 @@
                 "ConnectivityService");
     }
 
+    private void enforceNetworkStackSettingsOrSetup() {
+        enforceAnyPermissionOf(
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD,
+            android.Manifest.permission.NETWORK_STACK);
+    }
+
     private boolean checkNetworkStackPermission() {
         return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.NETWORK_STACK);
@@ -1798,7 +1815,8 @@
 
     private void sendStickyBroadcast(Intent intent) {
         synchronized (this) {
-            if (!mSystemReady) {
+            if (!mSystemReady
+                    && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 mInitialBroadcast = new Intent(intent);
             }
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1847,8 +1865,6 @@
                 mInitialBroadcast = null;
             }
         }
-        // load the global proxy at startup
-        mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
 
         // Try bringing up tracker, but KeyStore won't be ready yet for secondary users so wait
         // for user to unlock device too.
@@ -3089,7 +3105,7 @@
                     break;
                 }
                 case EVENT_APPLY_GLOBAL_HTTP_PROXY: {
-                    handleDeprecatedGlobalHttpProxy();
+                    mProxyTracker.loadDeprecatedGlobalHttpProxy();
                     break;
                 }
                 case EVENT_PROXY_HAS_CHANGED: {
@@ -3483,29 +3499,6 @@
         }
     }
 
-    private void handleDeprecatedGlobalHttpProxy() {
-        final String proxy = Settings.Global.getString(mContext.getContentResolver(),
-                Settings.Global.HTTP_PROXY);
-        if (!TextUtils.isEmpty(proxy)) {
-            String data[] = proxy.split(":");
-            if (data.length == 0) {
-                return;
-            }
-
-            final String proxyHost = data[0];
-            int proxyPort = 8080;
-            if (data.length > 1) {
-                try {
-                    proxyPort = Integer.parseInt(data[1]);
-                } catch (NumberFormatException e) {
-                    return;
-                }
-            }
-            final ProxyInfo p = new ProxyInfo(proxyHost, proxyPort, "");
-            setGlobalProxy(p);
-        }
-    }
-
     private static class SettingsObserver extends ContentObserver {
         final private HashMap<Uri, Integer> mUriEventMap;
         final private Context mContext;
@@ -4008,7 +4001,7 @@
 
     @Override
     public void setAirplaneMode(boolean enable) {
-        enforceConnectivityInternalPermission();
+        enforceNetworkStackSettingsOrSetup();
         final long ident = Binder.clearCallingIdentity();
         try {
             final ContentResolver cr = mContext.getContentResolver();
@@ -5537,15 +5530,7 @@
 
             if (networkAgent.isVPN()) {
                 // Temporarily disable the default proxy (not global).
-                synchronized (mProxyTracker.mProxyLock) {
-                    if (!mProxyTracker.mDefaultProxyDisabled) {
-                        mProxyTracker.mDefaultProxyDisabled = true;
-                        if (mProxyTracker.mGlobalProxy == null
-                                && mProxyTracker.mDefaultProxy != null) {
-                            mProxyTracker.sendProxyBroadcast(null);
-                        }
-                    }
-                }
+                mProxyTracker.setDefaultProxyEnabled(false);
                 // TODO: support proxy per network.
             }
 
@@ -5567,15 +5552,7 @@
         } else if (state == NetworkInfo.State.DISCONNECTED) {
             networkAgent.asyncChannel.disconnect();
             if (networkAgent.isVPN()) {
-                synchronized (mProxyTracker.mProxyLock) {
-                    if (mProxyTracker.mDefaultProxyDisabled) {
-                        mProxyTracker.mDefaultProxyDisabled = false;
-                        if (mProxyTracker.mGlobalProxy == null
-                                && mProxyTracker.mDefaultProxy != null) {
-                            mProxyTracker.sendProxyBroadcast(mProxyTracker.mDefaultProxy);
-                        }
-                    }
-                }
+                mProxyTracker.setDefaultProxyEnabled(true);
                 updateUids(networkAgent, networkAgent.networkCapabilities, null);
             }
             disconnectAndDestroyNetwork(networkAgent);
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
index 96ce6a4..6677541 100644
--- a/services/core/java/com/android/server/LooperStatsService.java
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -109,14 +109,28 @@
                 "max_latency_micros",
                 "total_cpu_micros",
                 "max_cpu_micros",
+                "recorded_delay_message_count",
+                "total_delay_millis",
+                "max_delay_millis",
                 "exception_count"));
         pw.println(header);
         for (LooperStats.ExportedEntry entry : entries) {
-            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.workSourceUid,
-                    entry.threadName, entry.handlerClassName, entry.messageName,
-                    entry.isInteractive, entry.messageCount, entry.recordedMessageCount,
-                    entry.totalLatencyMicros, entry.maxLatencyMicros, entry.cpuUsageMicros,
-                    entry.maxCpuUsageMicros, entry.exceptionCount);
+            pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
+                    entry.workSourceUid,
+                    entry.threadName,
+                    entry.handlerClassName,
+                    entry.messageName,
+                    entry.isInteractive,
+                    entry.messageCount,
+                    entry.recordedMessageCount,
+                    entry.totalLatencyMicros,
+                    entry.maxLatencyMicros,
+                    entry.cpuUsageMicros,
+                    entry.maxCpuUsageMicros,
+                    entry.recordedDelayMessageCount,
+                    entry.delayMillis,
+                    entry.maxDelayMillis,
+                    entry.exceptionCount);
         }
     }
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index de930f7..cf39e95 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -57,6 +57,7 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.INetd;
+import android.net.TetherStatsParcel;
 import android.net.INetworkManagementEventObserver;
 import android.net.ITetheringStatsProvider;
 import android.net.InterfaceConfiguration;
@@ -1844,31 +1845,30 @@
                 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
             }
 
-            final PersistableBundle bundle;
+            final TetherStatsParcel[] tetherStatsVec;
             try {
-                bundle = mNetdService.tetherGetStats();
+                tetherStatsVec = mNetdService.tetherGetStats();
             } catch (RemoteException | ServiceSpecificException e) {
                 throw new IllegalStateException("problem parsing tethering stats: ", e);
             }
 
             final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
-                    bundle.size());
+                tetherStatsVec.length);
             final NetworkStats.Entry entry = new NetworkStats.Entry();
 
-            for (String iface : bundle.keySet()) {
-                long[] statsArray = bundle.getLongArray(iface);
+            for (TetherStatsParcel tetherStats : tetherStatsVec) {
                 try {
-                    entry.iface = iface;
+                    entry.iface = tetherStats.iface;
                     entry.uid = UID_TETHERING;
                     entry.set = SET_DEFAULT;
                     entry.tag = TAG_NONE;
-                    entry.rxBytes   = statsArray[INetd.TETHER_STATS_RX_BYTES];
-                    entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
-                    entry.txBytes   = statsArray[INetd.TETHER_STATS_TX_BYTES];
-                    entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
+                    entry.rxBytes   = tetherStats.rxBytes;
+                    entry.rxPackets = tetherStats.rxPackets;
+                    entry.txBytes   = tetherStats.txBytes;
+                    entry.txPackets = tetherStats.txPackets;
                     stats.combineValues(entry);
                 } catch (ArrayIndexOutOfBoundsException e) {
-                    throw new IllegalStateException("invalid tethering stats for " + iface, e);
+                    throw new IllegalStateException("invalid tethering stats " + e);
                 }
             }
 
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index fb8894b..591ec00 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -49,6 +49,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.VoLteServiceState;
 import android.util.LocalLog;
+import android.util.StatsLog;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
@@ -1719,8 +1720,12 @@
         try {
             if (state == TelephonyManager.CALL_STATE_IDLE) {
                 mBatteryStats.notePhoneOff();
+                StatsLog.write(StatsLog.PHONE_STATE_CHANGED,
+                        StatsLog.PHONE_STATE_CHANGED__STATE__OFF);
             } else {
                 mBatteryStats.notePhoneOn();
+                StatsLog.write(StatsLog.PHONE_STATE_CHANGED,
+                        StatsLog.PHONE_STATE_CHANGED__STATE__ON);
             }
         } catch (RemoteException e) {
             /* The remote entity disappeared, we can safely ignore the exception. */
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index a648b09a..95a8e2a 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -1087,7 +1087,7 @@
         if (top == null) {
             return false;
         }
-        mSupervisor.moveFocusableActivityToTop(top, reason);
+        top.moveFocusableActivityToTop(reason);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java b/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
deleted file mode 100644
index f44ee7a..0000000
--- a/services/core/java/com/android/server/am/ActivityLaunchParamsModifier.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo;
-import android.graphics.Rect;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
-
-/**
- * An implementation of {@link LaunchParamsModifier}, which applies the launch bounds specified
- * inside {@link ActivityOptions#getLaunchBounds()}.
- */
-public class ActivityLaunchParamsModifier implements LaunchParamsModifier {
-    private final ActivityStackSupervisor mSupervisor;
-
-    ActivityLaunchParamsModifier(ActivityStackSupervisor activityStackSupervisor) {
-        mSupervisor = activityStackSupervisor;
-    }
-
-    @Override
-    public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
-            ActivityRecord activity, ActivityRecord source, ActivityOptions options,
-            LaunchParams currentParams, LaunchParams outParams) {
-        // We only care about figuring out bounds for activities.
-        if (activity == null) {
-            return RESULT_SKIP;
-        }
-
-        // Activity must be resizeable in the specified task.
-        if (!(mSupervisor.canUseActivityOptionsLaunchBounds(options)
-                && (activity.isResizeable() || (task != null && task.isResizeable())))) {
-            return RESULT_SKIP;
-        }
-
-        final Rect bounds = options.getLaunchBounds();
-
-        // Bounds weren't valid.
-        if (bounds == null || bounds.isEmpty()) {
-            return RESULT_SKIP;
-        }
-
-        outParams.mBounds.set(bounds);
-
-        // When this is the most explicit position specification so we should not allow further
-        // modification of the position.
-        return RESULT_DONE;
-    }
-}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 37167c6..acf7a73 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10184,6 +10184,7 @@
         synchronized (this) {
             sb.append("Process: ").append(processName).append("\n");
             sb.append("PID: ").append(process.pid).append("\n");
+            sb.append("UID: ").append(process.uid).append("\n");
             int flags = process.info.flags;
             IPackageManager pm = AppGlobals.getPackageManager();
             sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 18cdb05..7080e2b 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -110,7 +110,7 @@
  * data for Tron, logcat, event logs and {@link android.app.WaitResult}.
  *
  * Tests:
- * atest SystemMetricsFunctionalTests
+ * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
  */
 class ActivityMetricsLogger {
 
@@ -351,18 +351,24 @@
                 + " processRunning=" + processRunning
                 + " processSwitch=" + processSwitch);
 
-        // If we are already in an existing transition, only update the activity name, but not the
-        // other attributes.
         final int windowingMode = launchedActivity != null
                 ? launchedActivity.getWindowingMode()
                 : WINDOWING_MODE_UNDEFINED;
-
+        final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
         if (mCurrentTransitionStartTime == INVALID_START_TIME) {
+            // No transition is active ignore this launch.
             return;
         }
 
-        final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
+        if (launchedActivity != null && launchedActivity.nowVisible) {
+            // Launched activity is already visible. We cannot measure windows drawn delay.
+            reset(true /* abort */, info);
+            return;
+        }
+
         if (launchedActivity != null && info != null) {
+            // If we are already in an existing transition, only update the activity name, but not
+            // the other attributes.
             info.launchedActivity = launchedActivity;
             return;
         }
@@ -371,7 +377,6 @@
                 mWindowingModeTransitionInfo.size() > 0 && info == null;
         if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
                 || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
-
             // Failed to launch or it was not a process switch, so we don't care about the timing.
             reset(true /* abort */, info);
             return;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fe10baf..6bdceb2 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -84,11 +84,13 @@
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
@@ -215,6 +217,7 @@
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
+    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
     // TODO(b/67864419): Remove once recents component is overridden
     private static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
 
@@ -1348,6 +1351,42 @@
         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
     }
 
+    /** Move activity with its stack to front and make the stack focused. */
+    boolean moveFocusableActivityToTop(String reason) {
+        if (!isFocusable()) {
+            if (DEBUG_FOCUS) {
+                Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
+            }
+            return false;
+        }
+
+        final TaskRecord task = getTask();
+        final ActivityStack stack = getStack();
+        if (stack == null) {
+            Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
+                    + this + " task=" + task);
+            return false;
+        }
+
+        if (mStackSupervisor.getTopResumedActivity() == this) {
+            if (DEBUG_FOCUS) {
+                Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
+            }
+            return false;
+        }
+
+        if (DEBUG_FOCUS) {
+            Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
+        }
+
+        stack.moveToFront(reason, task);
+        // Report top activity change to tracking services and WM
+        if (mStackSupervisor.getTopResumedActivity() == this) {
+            // TODO(b/111361570): Support multiple focused apps in WM
+            service.setResumedActivityUncheckLocked(this, reason);
+        }
+        return true;
+    }
 
     /**
      * @return true if the activity contains windows that have
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6388423..864bf2d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -227,7 +227,7 @@
     }
 
     @Override
-    protected ConfigurationContainer getChildAt(int index) {
+    protected TaskRecord getChildAt(int index) {
         return mTaskHistory.get(index);
     }
 
@@ -3450,8 +3450,10 @@
         final String myReason = reason + " adjustFocus";
 
         if (next == r) {
-            mStackSupervisor.moveFocusableActivityToTop(mStackSupervisor.topRunningActivityLocked(),
-                    myReason);
+            final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+            if (top != null) {
+                top.moveFocusableActivityToTop(myReason);
+            }
             return;
         }
 
@@ -4662,7 +4664,9 @@
 
             // Set focus to the top running activity of this stack.
             final ActivityRecord r = topRunningActivityLocked();
-            mStackSupervisor.moveFocusableActivityToTop(r, reason);
+            if (r != null) {
+                r.moveFocusableActivityToTop(reason);
+            }
 
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
             if (noAnimation) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0477d73..8c8146c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -53,8 +53,8 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Display.TYPE_VIRTUAL;
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
@@ -63,7 +63,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
@@ -99,6 +98,7 @@
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
 import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+
 import static java.lang.Integer.MAX_VALUE;
 
 import android.Manifest;
@@ -199,7 +199,6 @@
 public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
         RecentTasks.Callbacks, RootWindowContainerListener {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
-    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
     private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -783,7 +782,7 @@
 
         // Only resume home activity if isn't finishing.
         if (r != null && !r.finishing) {
-            moveFocusableActivityToTop(r, myReason);
+            r.moveFocusableActivityToTop(myReason);
             return resumeFocusedStacksTopActivitiesLocked(r.getStack(), prev, null);
         }
         return mService.startHomeActivityLocked(mCurrentUser, myReason, displayId);
@@ -3359,41 +3358,6 @@
         mService.getTaskChangeNotificationController().notifyActivityPinned(r);
     }
 
-    /** Move activity with its stack to front and make the stack focused. */
-    // TODO(b/111363427): Move this method to ActivityRecord.
-    boolean moveFocusableActivityToTop(ActivityRecord r, String reason) {
-        if (r == null || !r.isFocusable()) {
-            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
-                    "moveActivityStackToFront: unfocusable r=" + r);
-            return false;
-        }
-
-        final TaskRecord task = r.getTask();
-        final ActivityStack stack = r.getStack();
-        if (stack == null) {
-            Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
-                    + r + " task=" + task);
-            return false;
-        }
-
-        if (r == getTopResumedActivity()) {
-            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
-                    "moveActivityStackToFront: already on top, r=" + r);
-            return false;
-        }
-
-        if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
-                "moveActivityStackToFront: r=" + r);
-
-        stack.moveToFront(reason, task);
-        // Report top activity change to tracking services and WM
-        if (r == getTopResumedActivity()) {
-            // TODO(b/111361570): Support multiple focused apps in WM
-            mService.setResumedActivityUncheckLocked(r, reason);
-        }
-        return true;
-    }
-
     ActivityRecord findTaskLocked(ActivityRecord r, int preferredDisplayId) {
         if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
         mTmpFindTaskResult.clear();
@@ -4456,10 +4420,6 @@
             if (!task.canBeLaunchedOnDisplay(actualDisplayId)) {
                 throw new IllegalStateException("Task resolved to incompatible display");
             }
-            // The task might have landed on a display different from requested.
-            // TODO(multi-display): Find proper stack for the task on the default display.
-            mService.setTaskWindowingMode(task.taskId,
-                    WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
             if (preferredDisplayId != actualDisplayId) {
                 Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
                 // Display a warning toast that we failed to put a task on a secondary display.
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 4789ff3..e51824f 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -44,6 +44,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.Bundle;
@@ -246,9 +247,9 @@
         if (PLATFORM_PACKAGE_NAME.equals(suspendingPackage)) {
             return interceptSuspendedByAdminPackage();
         }
-        final String dialogMessage = pmi.getSuspendedDialogMessage(suspendedPackage, mUserId);
+        final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage, mUserId);
         mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
-                suspendingPackage, dialogMessage, mUserId);
+                suspendingPackage, dialogInfo, mUserId);
         mCallingPid = mRealCallingPid;
         mCallingUid = mRealCallingUid;
         mResolvedType = null;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 2bd22e8..33f949f 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1477,7 +1477,7 @@
         if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
             newTask = true;
-            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
+            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
         } else if (mSourceRecord != null) {
             result = setTaskFromSourceRecord();
         } else if (mInTask != null) {
@@ -1606,13 +1606,18 @@
         mVoiceSession = voiceSession;
         mVoiceInteractor = voiceInteractor;
 
-        mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
-
         mLaunchParams.reset();
 
         mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
                 options, mLaunchParams);
 
+        if (mLaunchParams.hasPreferredDisplay()) {
+            mPreferredDisplayId = mLaunchParams.mPreferredDisplayId;
+        } else {
+            mPreferredDisplayId = DEFAULT_DISPLAY;
+        }
+        ensureValidPreferredDisplayId(r);
+
         mLaunchMode = r.launchMode;
 
         mLaunchFlags = adjustLaunchFlagsToDocumentMode(
@@ -1704,6 +1709,24 @@
         mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
     }
 
+    /**
+     * Ensure preferred display ID matches the starting activity.
+     */
+    private void ensureValidPreferredDisplayId(ActivityRecord startingActivity) {
+        // Check if the Activity is a VR activity. If so, the activity should be launched in
+        // main display.
+        if (startingActivity != null && startingActivity.requestedVrComponent != null) {
+            mPreferredDisplayId = DEFAULT_DISPLAY;
+        }
+
+        // Get the virtual display ID from ActivityStackManagerService. If that's set we should
+        // always use that.
+        final int displayId = mService.mVr2dDisplayId;
+        if (displayId != INVALID_DISPLAY) {
+            mPreferredDisplayId = displayId;
+        }
+    }
+
     private void sendNewTaskResultRequestIfNeeded() {
         final ActivityStack sourceStack = mStartActivity.resultTo != null
                 ? mStartActivity.resultTo.getStack() : null;
@@ -1883,44 +1906,6 @@
     }
 
     /**
-     * Returns the ID of the display to use for a new activity. If the device is in VR mode,
-     * then return the Vr mode's virtual display ID. If not,  if the activity was started with
-     * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
-     * set, use that to launch the activity.
-     */
-    private int getPreferedDisplayId(
-            ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
-        // Check if the Activity is a VR activity. If so, the activity should be launched in
-        // main display.
-        if (startingActivity != null && startingActivity.requestedVrComponent != null) {
-            return DEFAULT_DISPLAY;
-        }
-
-        // Get the virtual display id from ActivityManagerService.
-        int displayId = mService.mVr2dDisplayId;
-        if (displayId != INVALID_DISPLAY) {
-            if (DEBUG_STACK) {
-                Slog.d(TAG, "getSourceDisplayId :" + displayId);
-            }
-            return displayId;
-        }
-
-        // If the caller requested a display, prefer that display.
-        final int launchDisplayId =
-                (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
-        if (launchDisplayId != INVALID_DISPLAY) {
-            return launchDisplayId;
-        }
-
-        displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
-        // If the activity has a displayId set explicitly, launch it on the same displayId.
-        if (displayId != INVALID_DISPLAY) {
-            return displayId;
-        }
-        return DEFAULT_DISPLAY;
-    }
-
-    /**
      * Figure out which task and activity to bring to front when we have found an existing matching
      * activity record in history. May also clear the task if needed.
      * @param intentActivity Existing matching activity.
@@ -2125,8 +2110,7 @@
         mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
     }
 
-    private int setTaskFromReuseOrCreateNewTask(
-            TaskRecord taskToAffiliate, ActivityStack topStack) {
+    private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
         mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
 
         // Do no move the target stack to front yet, as we might bail if
@@ -2431,17 +2415,6 @@
             }
         }
         if (stack == null) {
-            // We first try to put the task in the first dynamic stack on home display.
-            final ActivityDisplay display = mSupervisor.getDefaultDisplay();
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                stack = display.getChildAt(stackNdx);
-                if (!stack.isOnHomeDisplay()) {
-                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                            "computeStackFocus: Setting focused stack=" + stack);
-                    return stack;
-                }
-            }
-            // If there is no suitable dynamic stack then we figure out which static stack to use.
             stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
         }
         if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 8e3eeae..b369b71 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -141,7 +141,6 @@
 import android.app.admin.DevicePolicyCache;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
-import android.app.servertransaction.ConfigurationChangeItem;
 import android.app.usage.UsageEvents;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -1707,7 +1706,7 @@
                     return;
                 }
                 final ActivityRecord r = stack.topRunningActivityLocked();
-                if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedStack")) {
+                if (r != null && r.moveFocusableActivityToTop("setFocusedStack")) {
                     mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
@@ -1728,7 +1727,7 @@
                     return;
                 }
                 final ActivityRecord r = task.topRunningActivityLocked();
-                if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedTask")) {
+                if (r != null && r.moveFocusableActivityToTop("setFocusedTask")) {
                     mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
@@ -4525,19 +4524,13 @@
             mAm.mHandler.sendMessage(msg);
         }
 
-        // TODO: Consider using mPidMap to update configurations for processes.
-        for (int i = mAm.mLruProcesses.size() - 1; i >= 0; i--) {
-            ProcessRecord app = mAm.mLruProcesses.get(i);
-            try {
-                if (app.thread != null) {
-                    if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
-                            + app.processName + " new config " + configCopy);
-                    getLifecycleManager().scheduleTransaction(app.thread,
-                            ConfigurationChangeItem.obtain(configCopy));
-                }
-            } catch (Exception e) {
-                Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e);
+        for (int i = mPidMap.size() - 1; i >= 0; i--) {
+            WindowProcessController app = mPidMap.get(mPidMap.keyAt(i));
+            if (DEBUG_CONFIGURATION) {
+                Slog.v(TAG_CONFIGURATION, "Update process config of "
+                        + app.mName + " to new config " + configCopy);
             }
+            app.onConfigurationChanged(configCopy);
         }
 
         Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
@@ -5554,7 +5547,7 @@
                     throw new IllegalArgumentException(
                             "setFocusedActivity: No activity record matching token=" + token);
                 }
-                if (mStackSupervisor.moveFocusableActivityToTop(r, "setFocusedActivity")) {
+                if (r.moveFocusableActivityToTop("setFocusedActivity")) {
                     mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
                 }
             }
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 2ca1344..09c152e 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -56,10 +56,6 @@
 
         sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
         sGlobalSettingToTypeMap.put(Settings.Global.ANGLE_ENABLED_APP, String.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_APP, String.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
         // add other global settings here...
     }
 
diff --git a/services/core/java/com/android/server/am/LaunchParamsController.java b/services/core/java/com/android/server/am/LaunchParamsController.java
index 6415c3e..218d908 100644
--- a/services/core/java/com/android/server/am/LaunchParamsController.java
+++ b/services/core/java/com/android/server/am/LaunchParamsController.java
@@ -16,6 +16,13 @@
 
 package com.android.server.am;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
 import android.annotation.IntDef;
 import android.app.ActivityOptions;
 import android.content.pm.ActivityInfo.WindowLayout;
@@ -26,13 +33,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.Display.INVALID_DISPLAY;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
-
 /**
  * {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between
  * registered {@link LaunchParamsModifier}s.
@@ -58,11 +58,7 @@
      */
     void registerDefaultModifiers(ActivityStackSupervisor supervisor) {
         // {@link TaskLaunchParamsModifier} handles window layout preferences.
-        registerModifier(new TaskLaunchParamsModifier());
-
-        // {@link ActivityLaunchParamsModifier} is the most specific modifier and thus should be
-        // registered last (applied first) out of the defaults.
-        registerModifier(new ActivityLaunchParamsModifier(supervisor));
+        registerModifier(new TaskLaunchParamsModifier(supervisor));
     }
 
     /**
@@ -226,27 +222,41 @@
         @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
         @interface Result {}
 
-        // Returned when the modifier does not want to influence the bounds calculation
+        /** Returned when the modifier does not want to influence the bounds calculation */
         int RESULT_SKIP = 0;
-        // Returned when the modifier has changed the bounds and would like its results to be the
-        // final bounds applied.
+        /**
+         * Returned when the modifier has changed the bounds and would like its results to be the
+         * final bounds applied.
+         */
         int RESULT_DONE = 1;
-        // Returned when the modifier has changed the bounds but is okay with other modifiers
-        // influencing the bounds.
+        /**
+         * Returned when the modifier has changed the bounds but is okay with other modifiers
+         * influencing the bounds.
+         */
         int RESULT_CONTINUE = 2;
 
         /**
-         * Called when asked to calculate {@link LaunchParams}.
-         * @param task            The {@link TaskRecord} currently being positioned.
-         * @param layout          The specified {@link WindowLayout}.
-         * @param activity        The {@link ActivityRecord} currently being positioned.
-         * @param source          The {@link ActivityRecord} activity was started from.
-         * @param options         The {@link ActivityOptions} specified for the activity.
-         * @param currentParams   The current {@link LaunchParams}. This can differ from the initial
-         *                        params as it represents the modified params up to this point.
-         * @param outParams       The resulting {@link LaunchParams} after all calculations.
-         * @return                A {@link Result} representing the result of the
-         *                        {@link LaunchParams} calculation.
+         * Returns the launch params that the provided activity launch params should be overridden
+         * to. {@link LaunchParamsModifier} can use this for various purposes, including: 1)
+         * Providing default bounds if the launch bounds have not been provided. 2) Repositioning
+         * the task so it doesn't get placed over an existing task. 3) Resizing the task so that its
+         * dimensions match the activity's requested orientation.
+         *
+         * @param task          Can be: 1) the target task in which the source activity wants to
+         *                      launch the target activity; 2) a newly created task that Android
+         *                      gives a chance to override its launching bounds; 3) {@code null} if
+         *                      this is called to override an activity's launching bounds.
+         * @param layout        Desired layout when activity is first launched.
+         * @param activity      Activity that is being started. This can be {@code null} on
+         *                      re-parenting an activity to a new task (e.g. for
+         *                      Picture-In-Picture). Tasks being created because an activity was
+         *                      launched should have this be non-null.
+         * @param source        the Activity that launched a new task. Could be {@code null}.
+         * @param options       {@link ActivityOptions} used to start the activity with.
+         * @param currentParams launching params after the process of last {@link
+         *                      LaunchParamsModifier}.
+         * @param outParams     the result params to be set.
+         * @return see {@link LaunchParamsModifier.Result}
          */
         @Result
         int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3ac7885..9e7ce32 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -162,9 +162,11 @@
     // LMK_TARGET <minfree> <minkillprio> ... (up to 6 pairs)
     // LMK_PROCPRIO <pid> <uid> <prio>
     // LMK_PROCREMOVE <pid>
+    // LMK_PROCPURGE
     static final byte LMK_TARGET = 0;
     static final byte LMK_PROCPRIO = 1;
     static final byte LMK_PROCREMOVE = 2;
+    static final byte LMK_PROCPURGE = 3;
 
     // These are the various interesting memory levels that we will give to
     // the OOM killer.  Note that the OOM killer only supports 6 slots, so we
@@ -813,31 +815,46 @@
         return true;
     }
 
+    // Never call directly, use writeLmkd() instead
+    private static boolean writeLmkdCommand(ByteBuffer buf) {
+        try {
+            sLmkdOutputStream.write(buf.array(), 0, buf.position());
+        } catch (IOException ex) {
+            Slog.w(TAG, "Error writing to lowmemorykiller socket");
+
+            try {
+                sLmkdSocket.close();
+            } catch (IOException ex2) {
+            }
+
+            sLmkdSocket = null;
+            return false;
+        }
+        return true;
+    }
+
     private static void writeLmkd(ByteBuffer buf) {
 
         for (int i = 0; i < 3; i++) {
             if (sLmkdSocket == null) {
-                    if (openLmkdSocket() == false) {
-                        try {
-                            Thread.sleep(1000);
-                        } catch (InterruptedException ie) {
-                        }
-                        continue;
+                if (openLmkdSocket() == false) {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException ie) {
                     }
-            }
-
-            try {
-                sLmkdOutputStream.write(buf.array(), 0, buf.position());
-                return;
-            } catch (IOException ex) {
-                Slog.w(TAG, "Error writing to lowmemorykiller socket");
-
-                try {
-                    sLmkdSocket.close();
-                } catch (IOException ex2) {
+                    continue;
                 }
 
-                sLmkdSocket = null;
+                // Purge any previously registered pids
+                ByteBuffer purge_buf = ByteBuffer.allocate(4);
+                purge_buf.putInt(LMK_PROCPURGE);
+                if (writeLmkdCommand(purge_buf) == false) {
+                    // Write failed, skip the rest and retry
+                    continue;
+                }
+            }
+            if (writeLmkdCommand(buf)) {
+                return;
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
index 92f1cc3..fd34d18 100644
--- a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
@@ -16,304 +16,770 @@
 
 package com.android.server.am;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.graphics.Rect;
+import android.os.Build;
 import android.util.Slog;
 import android.view.Gravity;
-import com.android.internal.annotations.VisibleForTesting;
+
 import com.android.server.am.LaunchParamsController.LaunchParams;
 import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
- * Determines where a launching task should be positioned and sized on the display.
- *
- * The modifier is fairly simple. For the new task it tries default position based on the gravity
- * and compares corners of the task with corners of existing tasks. If some two pairs of corners are
- * sufficiently close enough, it shifts the bounds of the new task and tries again. When it exhausts
- * all possible shifts, it gives up and puts the task in the original position.
- *
- * Note that the only gravities of concern are the corners and the center.
+ * The class that defines the default launch params for tasks.
  */
 class TaskLaunchParamsModifier implements LaunchParamsModifier {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_AM;
+    private static final boolean DEBUG = false;
 
-    // Determines how close window frames/corners have to be to call them colliding.
-    private static final int BOUNDS_CONFLICT_MIN_DISTANCE = 4;
+    // A mask for SUPPORTS_SCREEN that indicates the activity supports resize.
+    private static final int SUPPORTS_SCREEN_RESIZEABLE_MASK =
+            ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
+                    | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
+                    | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
+                    | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
+                    | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
+                    | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
 
-    // Task will receive dimensions based on available dimensions divided by this.
-    private static final int WINDOW_SIZE_DENOMINATOR = 2;
+    // Screen size of Nexus 5x
+    private static final int DEFAULT_PORTRAIT_PHONE_WIDTH_DP = 412;
+    private static final int DEFAULT_PORTRAIT_PHONE_HEIGHT_DP = 732;
 
-    // Task will receive margins based on available dimensions divided by this.
-    private static final int MARGIN_SIZE_DENOMINATOR = 4;
+    // Allowance of size matching.
+    private static final int EPSILON = 2;
 
-    // If task bounds collide with some other, we will step and try again until we find a good
-    // position. The step will be determined by using dimensions and dividing it by this.
+    // Cascade window offset.
+    private static final int CASCADING_OFFSET_DP = 75;
+
+    // Threshold how close window corners have to be to call them colliding.
+    private static final int BOUNDS_CONFLICT_THRESHOLD = 4;
+
+    // Divide display size by this number to get each step to adjust bounds to avoid conflict.
     private static final int STEP_DENOMINATOR = 16;
 
     // We always want to step by at least this.
     private static final int MINIMAL_STEP = 1;
 
-    // Used to indicate if positioning algorithm is allowed to restart from the beginning, when it
-    // reaches the end of stack bounds.
-    private static final boolean ALLOW_RESTART = true;
+    private final ActivityStackSupervisor mSupervisor;
+    private final Rect mTmpBounds = new Rect();
+    private final int[] mTmpDirections = new int[2];
 
-    private static final int SHIFT_POLICY_DIAGONAL_DOWN = 1;
-    private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
-    private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
+    private StringBuilder mLogBuilder;
 
-    private final Rect mAvailableRect = new Rect();
-    private final Rect mTmpProposal = new Rect();
-    private final Rect mTmpOriginal = new Rect();
+    TaskLaunchParamsModifier(ActivityStackSupervisor supervisor) {
+        mSupervisor = supervisor;
+    }
 
-    /**
-     * Tries to set task's bound in a way that it won't collide with any other task. By colliding
-     * we mean that two tasks have left-top corner very close to each other, so one might get
-     * obfuscated by the other one.
-     */
     @Override
     public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
                            ActivityRecord activity, ActivityRecord source, ActivityOptions options,
                            LaunchParams currentParams, LaunchParams outParams) {
-        // We can only apply positioning if we're in a freeform stack.
-        if (task == null || task.getStack() == null || !task.inFreeformWindowingMode()) {
-            return RESULT_SKIP;
+        initLogBuilder(task, activity);
+        final int result = calculate(task, layout, activity, source, options, currentParams,
+                outParams);
+        outputLog();
+        return result;
+    }
+
+    private int calculate(TaskRecord task, ActivityInfo.WindowLayout layout,
+            ActivityRecord activity, ActivityRecord source, ActivityOptions options,
+            LaunchParams currentParams, LaunchParams outParams) {
+        // STEP 1: Determine the display to launch the activity/task.
+        final int displayId = getPreferredLaunchDisplay(options, source, currentParams);
+        outParams.mPreferredDisplayId = displayId;
+        ActivityDisplay display = mSupervisor.getActivityDisplay(displayId);
+        if (DEBUG) {
+            appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode="
+                    + display.getWindowingMode());
         }
 
-        final ArrayList<TaskRecord> tasks = task.getStack().getAllTasks();
-
-        mAvailableRect.set(task.getParent().getBounds());
-
-        final Rect resultBounds = outParams.mBounds;
-
-        if (layout == null) {
-            positionCenter(tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
-                    getFreeformHeight(mAvailableRect), resultBounds);
-            return RESULT_CONTINUE;
+        final ActivityRecord root;
+        if (task != null) {
+            root = (task.getRootActivity() == null ? activity : task.getRootActivity());
+        } else {
+            root = activity;
         }
-
-        int width = getFinalWidth(layout, mAvailableRect);
-        int height = getFinalHeight(layout, mAvailableRect);
-        int verticalGravity = layout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
-        int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
-        if (verticalGravity == Gravity.TOP) {
-            if (horizontalGravity == Gravity.RIGHT) {
-                positionTopRight(tasks, mAvailableRect, width, height, resultBounds);
+        // STEP 2: Resolve launch windowing mode.
+        // STEP 2.1: Determine if any parameter has specified initial bounds. That might be the
+        // launch bounds from activity options, or size/gravity passed in layout. It also treat the
+        // launch windowing mode in options as a suggestion for future resolution.
+        int launchMode = options != null ? options.getLaunchWindowingMode()
+                : WINDOWING_MODE_UNDEFINED;
+        // hasInitialBounds is set if either activity options or layout has specified bounds. If
+        // that's set we'll skip some adjustments later to avoid overriding the initial bounds.
+        boolean hasInitialBounds = false;
+        final boolean canApplyFreeformPolicy =
+                canApplyFreeformWindowPolicy(display, root, launchMode);
+        if (mSupervisor.canUseActivityOptionsLaunchBounds(options) && canApplyFreeformPolicy) {
+            hasInitialBounds = true;
+            launchMode = launchMode == WINDOWING_MODE_UNDEFINED
+                    ? WINDOWING_MODE_FREEFORM
+                    : launchMode;
+            outParams.mBounds.set(options.getLaunchBounds());
+            if (DEBUG) appendLog("activity-options-bounds=" + outParams.mBounds);
+        } else if (launchMode == WINDOWING_MODE_PINNED) {
+            // System controls PIP window's bounds, so don't apply launch bounds.
+            if (DEBUG) appendLog("empty-window-layout-for-pip");
+        } else if (launchMode == WINDOWING_MODE_FULLSCREEN) {
+            if (DEBUG) appendLog("activity-options-fullscreen=" + outParams.mBounds);
+        } else if (layout != null && canApplyFreeformPolicy) {
+            getLayoutBounds(display, root, layout, mTmpBounds);
+            if (!mTmpBounds.isEmpty()) {
+                launchMode = WINDOWING_MODE_FREEFORM;
+                outParams.mBounds.set(mTmpBounds);
+                hasInitialBounds = true;
+                if (DEBUG) appendLog("bounds-from-layout=" + outParams.mBounds);
             } else {
-                positionTopLeft(tasks, mAvailableRect, width, height, resultBounds);
+                if (DEBUG) appendLog("empty-window-layout");
             }
-        } else if (verticalGravity == Gravity.BOTTOM) {
-            if (horizontalGravity == Gravity.RIGHT) {
-                positionBottomRight(tasks, mAvailableRect, width, height, resultBounds);
-            } else {
-                positionBottomLeft(tasks, mAvailableRect, width, height, resultBounds);
+        }
+
+        // STEP 2.2: Check if previous modifier or the controller (referred as "callers" below) has
+        // some opinions on launch mode and launch bounds. If they have opinions and there is no
+        // initial bounds set in parameters. Note the check on display ID is also input param
+        // related because we always defer to callers' suggestion if there is no specific display ID
+        // in options or from source activity.
+        //
+        // If opinions from callers don't need any further resolution, we try to honor that as is as
+        // much as possible later.
+
+        // Flag to indicate if current param needs no further resolution. It's true it current
+        // param isn't freeform mode, or it already has launch bounds.
+        boolean fullyResolvedCurrentParam = false;
+        // We inherit launch params from previous modifiers or LaunchParamsController if options,
+        // layout and display conditions are not contradictory to their suggestions. It's important
+        // to carry over their values because LaunchParamsController doesn't automatically do that.
+        if (!currentParams.isEmpty() && !hasInitialBounds
+                && (!currentParams.hasPreferredDisplay()
+                    || displayId == currentParams.mPreferredDisplayId)) {
+            if (currentParams.hasWindowingMode()) {
+                launchMode = currentParams.mWindowingMode;
+                fullyResolvedCurrentParam = (launchMode != WINDOWING_MODE_FREEFORM);
+                if (DEBUG) {
+                    appendLog("inherit-" + WindowConfiguration.windowingModeToString(launchMode));
+                }
+            }
+
+            if (!currentParams.mBounds.isEmpty()) {
+                outParams.mBounds.set(currentParams.mBounds);
+                fullyResolvedCurrentParam = true;
+                if (DEBUG) appendLog("inherit-bounds=" + outParams.mBounds);
+            }
+        }
+
+        // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the policy
+        // that legacy (pre-D) apps and those apps that can't handle multiple screen density well
+        // are forced to be maximized. The rest of this step is to define the default policy when
+        // there is no initial bounds or a fully resolved current params from callers. Right now we
+        // launch all possible tasks/activities that can handle freeform into freeform mode.
+        if (display.inFreeformWindowingMode()) {
+            if (launchMode == WINDOWING_MODE_PINNED) {
+                if (DEBUG) appendLog("picture-in-picture");
+            } else if (isTaskForcedMaximized(root)) {
+                // We're launching an activity that probably can't handle resizing nicely, so force
+                // it to be maximized even someone suggests launching it in freeform using launch
+                // options.
+                launchMode = WINDOWING_MODE_FULLSCREEN;
+                outParams.mBounds.setEmpty();
+                if (DEBUG) appendLog("forced-maximize");
+            } else if (fullyResolvedCurrentParam) {
+                // Don't adjust launch mode if that's inherited, except when we're launching an
+                // activity that should be forced to maximize.
+                if (DEBUG) appendLog("skip-adjustment-fully-resolved-params");
+            } else if (launchMode != WINDOWING_MODE_FREEFORM
+                    && (isNOrGreater(root) || isPreNResizeable(root))) {
+                // We're launching a pre-N and post-D activity that supports resizing, or a post-N
+                // activity. They can handle freeform nicely so launch them in freeform.
+                // Use undefined because we know we're in a freeform display.
+                launchMode = WINDOWING_MODE_UNDEFINED;
+                if (DEBUG) appendLog("should-be-freeform");
             }
         } else {
-            // Some fancy gravity setting that we don't support yet. We just put the activity in the
-            // center.
-            Slog.w(TAG, "Received unsupported gravity: " + layout.gravity
-                    + ", positioning in the center instead.");
-            positionCenter(tasks, mAvailableRect, width, height, resultBounds);
+            if (DEBUG) appendLog("non-freeform-display");
+        }
+        // If launch mode matches display windowing mode, let it inherit from display.
+        outParams.mWindowingMode = launchMode == display.getWindowingMode()
+                ? WINDOWING_MODE_UNDEFINED : launchMode;
+
+        // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
+        // requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
+        // for all other windowing modes that's not freeform mode. One can read comments in
+        // relevant methods to further understand this step.
+        //
+        // We skip making adjustments if the params are fully resolved from previous results and
+        // trust that they are valid.
+        if (!fullyResolvedCurrentParam) {
+            final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
+                    : display.getWindowingMode();
+            if (source != null && source.inFreeformWindowingMode()
+                    && resolvedMode == WINDOWING_MODE_FREEFORM
+                    && outParams.mBounds.isEmpty()
+                    && source.getDisplayId() == display.mDisplayId) {
+                // Set bounds to be not very far from source activity.
+                cascadeBounds(source.getBounds(), display, outParams.mBounds);
+            }
+            getTaskBounds(root, display, layout, resolvedMode, hasInitialBounds, outParams.mBounds);
         }
 
         return RESULT_CONTINUE;
     }
 
-    @VisibleForTesting
-    static int getFreeformStartLeft(Rect bounds) {
-        return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
-    }
-
-    @VisibleForTesting
-    static int getFreeformStartTop(Rect bounds) {
-        return bounds.top + bounds.height() / MARGIN_SIZE_DENOMINATOR;
-    }
-
-    @VisibleForTesting
-    static int getFreeformWidth(Rect bounds) {
-        return bounds.width() / WINDOW_SIZE_DENOMINATOR;
-    }
-
-    @VisibleForTesting
-    static int getFreeformHeight(Rect bounds) {
-        return bounds.height() / WINDOW_SIZE_DENOMINATOR;
-    }
-
-    @VisibleForTesting
-    static int getHorizontalStep(Rect bounds) {
-        return Math.max(bounds.width() / STEP_DENOMINATOR, MINIMAL_STEP);
-    }
-
-    @VisibleForTesting
-    static int getVerticalStep(Rect bounds) {
-        return Math.max(bounds.height() / STEP_DENOMINATOR, MINIMAL_STEP);
-    }
-
-
-
-    private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
-        int width = getFreeformWidth(availableRect);
-        if (windowLayout.width > 0) {
-            width = windowLayout.width;
+    private int getPreferredLaunchDisplay(@Nullable ActivityOptions options,
+            ActivityRecord source, LaunchParams currentParams) {
+        int displayId = INVALID_DISPLAY;
+        final int optionLaunchId = options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
+        if (optionLaunchId != INVALID_DISPLAY) {
+            if (DEBUG) appendLog("display-from-option=" + optionLaunchId);
+            displayId = optionLaunchId;
         }
-        if (windowLayout.widthFraction > 0) {
-            width = (int) (availableRect.width() * windowLayout.widthFraction);
+
+        if (displayId == INVALID_DISPLAY && source != null) {
+            final int sourceDisplayId = source.getDisplayId();
+            if (DEBUG) appendLog("display-from-source=" + sourceDisplayId);
+            displayId = sourceDisplayId;
         }
-        return width;
-    }
 
-    private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
-        int height = getFreeformHeight(availableRect);
-        if (windowLayout.height > 0) {
-            height = windowLayout.height;
+        if (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) == null) {
+            displayId = INVALID_DISPLAY;
         }
-        if (windowLayout.heightFraction > 0) {
-            height = (int) (availableRect.height() * windowLayout.heightFraction);
+        displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;
+
+        displayId = (displayId == INVALID_DISPLAY) ? DEFAULT_DISPLAY : displayId;
+
+        return displayId;
+    }
+
+    private boolean canApplyFreeformWindowPolicy(@NonNull ActivityDisplay display,
+            @NonNull ActivityRecord root, int launchMode) {
+        return display.inFreeformWindowingMode() || launchMode == WINDOWING_MODE_FREEFORM
+                || root.isResizeable();
+    }
+
+    private void getLayoutBounds(@NonNull ActivityDisplay display, @NonNull ActivityRecord root,
+            @NonNull ActivityInfo.WindowLayout windowLayout, @NonNull Rect outBounds) {
+        final int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+        final int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+        if (!windowLayout.hasSpecifiedSize() && verticalGravity == 0 && horizontalGravity == 0) {
+            outBounds.setEmpty();
+            return;
         }
-        return height;
-    }
 
-    private void positionBottomLeft(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
-            int height, Rect result) {
-        mTmpProposal.set(availableRect.left, availableRect.bottom - height,
-                availableRect.left + width, availableRect.bottom);
-        position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT,
-                result);
-    }
+        final Rect bounds = display.getBounds();
+        final int defaultWidth = bounds.width();
+        final int defaultHeight = bounds.height();
 
-    private void positionBottomRight(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
-            int height, Rect result) {
-        mTmpProposal.set(availableRect.right - width, availableRect.bottom - height,
-                availableRect.right, availableRect.bottom);
-        position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT,
-                result);
-    }
-
-    private void positionTopLeft(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
-            int height, Rect result) {
-        mTmpProposal.set(availableRect.left, availableRect.top,
-                availableRect.left + width, availableRect.top + height);
-        position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT,
-                result);
-    }
-
-    private void positionTopRight(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
-            int height, Rect result) {
-        mTmpProposal.set(availableRect.right - width, availableRect.top,
-                availableRect.right, availableRect.top + height);
-        position(tasks, availableRect, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT,
-                result);
-    }
-
-    private void positionCenter(ArrayList<TaskRecord> tasks, Rect availableRect, int width,
-            int height, Rect result) {
-        final int defaultFreeformLeft = getFreeformStartLeft(availableRect);
-        final int defaultFreeformTop = getFreeformStartTop(availableRect);
-        mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop,
-                defaultFreeformLeft + width, defaultFreeformTop + height);
-        position(tasks, availableRect, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN,
-                result);
-    }
-
-    private void position(ArrayList<TaskRecord> tasks, Rect availableRect,
-            Rect proposal, boolean allowRestart, int shiftPolicy, Rect result) {
-        mTmpOriginal.set(proposal);
-        boolean restarted = false;
-        while (boundsConflict(proposal, tasks)) {
-            // Unfortunately there is already a task at that spot, so we need to look for some
-            // other place.
-            shiftStartingPoint(proposal, availableRect, shiftPolicy);
-            if (shiftedTooFar(proposal, availableRect, shiftPolicy)) {
-                // We don't want the task to go outside of the stack, because it won't look
-                // nice. Depending on the starting point we either restart, or immediately give up.
-                if (!allowRestart) {
-                    proposal.set(mTmpOriginal);
-                    break;
-                }
-                // We must have started not from the top. Let's restart from there because there
-                // might be some space there.
-                proposal.set(availableRect.left, availableRect.top,
-                        availableRect.left + proposal.width(),
-                        availableRect.top + proposal.height());
-                restarted = true;
+        int width;
+        int height;
+        if (!windowLayout.hasSpecifiedSize()) {
+            outBounds.setEmpty();
+            getTaskBounds(root, display, windowLayout, WINDOWING_MODE_FREEFORM,
+                    /* hasInitialBounds */ false, outBounds);
+            width = outBounds.width();
+            height = outBounds.height();
+        } else {
+            width = defaultWidth;
+            if (windowLayout.width > 0 && windowLayout.width < defaultWidth) {
+                width = windowLayout.width;
+            } else if (windowLayout.widthFraction > 0 && windowLayout.widthFraction < 1.0f) {
+                width = (int) (width * windowLayout.widthFraction);
             }
-            if (restarted && (proposal.left > getFreeformStartLeft(availableRect)
-                    || proposal.top > getFreeformStartTop(availableRect))) {
-                // If we restarted and crossed the initial position, let's not struggle anymore.
-                // The user already must have ton of tasks visible, we can just smack the new
-                // one in the center.
-                proposal.set(mTmpOriginal);
-                break;
+
+            height = defaultHeight;
+            if (windowLayout.height > 0 && windowLayout.height < defaultHeight) {
+                height = windowLayout.height;
+            } else if (windowLayout.heightFraction > 0 && windowLayout.heightFraction < 1.0f) {
+                height = (int) (height * windowLayout.heightFraction);
             }
         }
-        result.set(proposal);
-    }
 
-    private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) {
-        switch (shiftPolicy) {
-            case SHIFT_POLICY_HORIZONTAL_LEFT:
-                return start.left < availableRect.left;
-            case SHIFT_POLICY_HORIZONTAL_RIGHT:
-                return start.right > availableRect.right;
-            default: // SHIFT_POLICY_DIAGONAL_DOWN
-                return start.right > availableRect.right || start.bottom > availableRect.bottom;
+        final float fractionOfHorizontalOffset;
+        switch (horizontalGravity) {
+            case Gravity.LEFT:
+                fractionOfHorizontalOffset = 0f;
+                break;
+            case Gravity.RIGHT:
+                fractionOfHorizontalOffset = 1f;
+                break;
+            default:
+                fractionOfHorizontalOffset = 0.5f;
         }
-    }
 
-    private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) {
-        final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect);
-        final int defaultFreeformStepVertical = getVerticalStep(availableRect);
-
-        switch (shiftPolicy) {
-            case SHIFT_POLICY_HORIZONTAL_LEFT:
-                posposal.offset(-defaultFreeformStepHorizontal, 0);
+        final float fractionOfVerticalOffset;
+        switch (verticalGravity) {
+            case Gravity.TOP:
+                fractionOfVerticalOffset = 0f;
                 break;
-            case SHIFT_POLICY_HORIZONTAL_RIGHT:
-                posposal.offset(defaultFreeformStepHorizontal, 0);
+            case Gravity.BOTTOM:
+                fractionOfVerticalOffset = 1f;
                 break;
-            default: // SHIFT_POLICY_DIAGONAL_DOWN:
-                posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical);
-                break;
+            default:
+                fractionOfVerticalOffset = 0.5f;
         }
+
+        outBounds.set(0, 0, width, height);
+        final int xOffset = (int) (fractionOfHorizontalOffset * (defaultWidth - width));
+        final int yOffset = (int) (fractionOfVerticalOffset * (defaultHeight - height));
+        outBounds.offset(xOffset, yOffset);
     }
 
-    private static boolean boundsConflict(Rect proposal, ArrayList<TaskRecord> tasks) {
-        for (int i = tasks.size() - 1; i >= 0; i--) {
-            final TaskRecord task = tasks.get(i);
-            if (!task.mActivities.isEmpty() && !task.matchParentBounds()) {
-                final Rect bounds = task.getOverrideBounds();
-                if (closeLeftTopCorner(proposal, bounds) || closeRightTopCorner(proposal, bounds)
-                        || closeLeftBottomCorner(proposal, bounds)
-                        || closeRightBottomCorner(proposal, bounds)) {
-                    return true;
-                }
+    /**
+     * Returns if task is forced to maximize.
+     *
+     * There are several cases where we force a task to maximize:
+     * 1) Root activity is targeting pre-Donut, which by default can't handle multiple screen
+     *    densities, so resizing will likely cause issues;
+     * 2) Root activity doesn't declare any flag that it supports any screen density, so resizing
+     *    may also cause issues;
+     * 3) Root activity is not resizeable, for which we shouldn't allow user resize it.
+     *
+     * @param root the root activity to check against.
+     * @return {@code true} if it should be forced to maximize; {@code false} otherwise.
+     */
+    private boolean isTaskForcedMaximized(@NonNull ActivityRecord root) {
+        if (root.appInfo.targetSdkVersion < Build.VERSION_CODES.DONUT
+                || (root.appInfo.flags & SUPPORTS_SCREEN_RESIZEABLE_MASK) == 0) {
+            return true;
+        }
+
+        return !root.isResizeable();
+    }
+
+    private boolean isNOrGreater(@NonNull ActivityRecord root) {
+        return root.appInfo.targetSdkVersion >= Build.VERSION_CODES.N;
+    }
+
+    /**
+     * Resolves activity requested orientation to 4 categories:
+     * 1) {@link ActivityInfo#SCREEN_ORIENTATION_LOCKED} indicating app wants to lock down
+     *    orientation;
+     * 2) {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE} indicating app wants to be in landscape;
+     * 3) {@link ActivityInfo#SCREEN_ORIENTATION_PORTRAIT} indicating app wants to be in portrait;
+     * 4) {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} indicating app can handle any
+     *    orientation.
+     *
+     * @param activity the activity to check
+     * @return corresponding resolved orientation value.
+     */
+    private int resolveOrientation(@NonNull ActivityRecord activity) {
+        int orientation = activity.info.screenOrientation;
+        switch (orientation) {
+            case SCREEN_ORIENTATION_NOSENSOR:
+            case SCREEN_ORIENTATION_LOCKED:
+                orientation = SCREEN_ORIENTATION_LOCKED;
+                break;
+            case SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+            case SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+            case SCREEN_ORIENTATION_USER_LANDSCAPE:
+            case SCREEN_ORIENTATION_LANDSCAPE:
+                if (DEBUG) appendLog("activity-requested-landscape");
+                orientation = SCREEN_ORIENTATION_LANDSCAPE;
+                break;
+            case SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+            case SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+            case SCREEN_ORIENTATION_USER_PORTRAIT:
+            case SCREEN_ORIENTATION_PORTRAIT:
+                if (DEBUG) appendLog("activity-requested-portrait");
+                orientation = SCREEN_ORIENTATION_PORTRAIT;
+                break;
+            default:
+                orientation = SCREEN_ORIENTATION_UNSPECIFIED;
+        }
+
+        return orientation;
+    }
+
+    private boolean isPreNResizeable(ActivityRecord root) {
+        return root.appInfo.targetSdkVersion < Build.VERSION_CODES.N && root.isResizeable();
+    }
+
+    private void cascadeBounds(@NonNull Rect srcBounds, @NonNull ActivityDisplay display,
+            @NonNull Rect outBounds) {
+        outBounds.set(srcBounds);
+        float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
+        final int defaultOffset = (int) (CASCADING_OFFSET_DP * density + 0.5f);
+
+        display.getBounds(mTmpBounds);
+        final int dx = Math.min(defaultOffset, Math.max(0, mTmpBounds.right - srcBounds.right));
+        final int dy = Math.min(defaultOffset, Math.max(0, mTmpBounds.bottom - srcBounds.bottom));
+        outBounds.offset(dx, dy);
+    }
+
+    private void getTaskBounds(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
+            @NonNull ActivityInfo.WindowLayout layout, int resolvedMode, boolean hasInitialBounds,
+            @NonNull Rect inOutBounds) {
+        if (resolvedMode == WINDOWING_MODE_FULLSCREEN) {
+            // We don't handle letterboxing here. Letterboxing will be handled by valid checks
+            // later.
+            inOutBounds.setEmpty();
+            if (DEBUG) appendLog("maximized-bounds");
+            return;
+        }
+
+        if (resolvedMode != WINDOWING_MODE_FREEFORM) {
+            // We don't apply freeform bounds adjustment to other windowing modes.
+            if (DEBUG) {
+                appendLog("skip-bounds-" + WindowConfiguration.windowingModeToString(resolvedMode));
+            }
+            return;
+        }
+
+        final int orientation = resolveOrientation(root, display, inOutBounds);
+        if (orientation != SCREEN_ORIENTATION_PORTRAIT
+                && orientation != SCREEN_ORIENTATION_LANDSCAPE) {
+            throw new IllegalStateException(
+                    "Orientation must be one of portrait or landscape, but it's "
+                    + ActivityInfo.screenOrientationToString(orientation));
+        }
+
+        // First we get the default size we want.
+        getDefaultFreeformSize(display, layout, orientation, mTmpBounds);
+        if (hasInitialBounds || sizeMatches(inOutBounds, mTmpBounds)) {
+            // We're here because either input parameters specified initial bounds, or the suggested
+            // bounds have the same size of the default freeform size. We should use the suggested
+            // bounds if possible -- so if app can handle the orientation we just use it, and if not
+            // we transpose the suggested bounds in-place.
+            if (orientation == orientationFromBounds(inOutBounds)) {
+                if (DEBUG) appendLog("freeform-size-orientation-match=" + inOutBounds);
+            } else {
+                // Meh, orientation doesn't match. Let's rotate inOutBounds in-place.
+                centerBounds(display, inOutBounds.height(), inOutBounds.width(), inOutBounds);
+                if (DEBUG) appendLog("freeform-orientation-mismatch=" + inOutBounds);
+            }
+        } else {
+            // We are here either because there is no suggested bounds, or the suggested bounds is
+            // a cascade from source activity. We should use the default freeform size and center it
+            // to the center of suggested bounds (or the display if no suggested bounds). The
+            // default size might be too big to center to source activity bounds in display, so we
+            // may need to move it back to the display.
+            centerBounds(display, mTmpBounds.width(), mTmpBounds.height(), inOutBounds);
+            adjustBoundsToFitInDisplay(display, inOutBounds);
+            if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
+        }
+
+        // Lastly we adjust bounds to avoid conflicts with other tasks as much as possible.
+        adjustBoundsToAvoidConflict(display, inOutBounds);
+    }
+
+    private int resolveOrientation(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
+            @NonNull Rect bounds) {
+        int orientation = resolveOrientation(root);
+
+        if (orientation == SCREEN_ORIENTATION_LOCKED) {
+            orientation = bounds.isEmpty() ? display.getConfiguration().orientation
+                    : orientationFromBounds(bounds);
+            if (DEBUG) {
+                appendLog(bounds.isEmpty() ? "locked-orientation-from-display=" + orientation
+                        : "locked-orientation-from-bounds=" + bounds);
             }
         }
+
+        if (orientation == SCREEN_ORIENTATION_UNSPECIFIED) {
+            orientation = bounds.isEmpty() ? SCREEN_ORIENTATION_PORTRAIT
+                    : orientationFromBounds(bounds);
+            if (DEBUG) {
+                appendLog(bounds.isEmpty() ? "default-portrait"
+                        : "orientation-from-bounds=" + bounds);
+            }
+        }
+
+        return orientation;
+    }
+
+    private void getDefaultFreeformSize(@NonNull ActivityDisplay display,
+            @NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) {
+        // Default size, which is letterboxing/pillarboxing in display. That's to say the large
+        // dimension of default size is the small dimension of display size, and the small dimension
+        // of default size is calculated to keep the same aspect ratio as the display's.
+        Rect displayBounds = display.getBounds();
+        final int portraitHeight = Math.min(displayBounds.width(), displayBounds.height());
+        final int otherDimension = Math.max(displayBounds.width(), displayBounds.height());
+        final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension;
+        final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight
+                : portraitWidth;
+        final int defaultHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitWidth
+                : portraitHeight;
+
+        // Get window size based on Nexus 5x screen, we assume that this is enough to show content
+        // of activities.
+        final float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
+        final int phonePortraitWidth = (int) (DEFAULT_PORTRAIT_PHONE_WIDTH_DP * density + 0.5f);
+        final int phonePortraitHeight = (int) (DEFAULT_PORTRAIT_PHONE_HEIGHT_DP * density + 0.5f);
+        final int phoneWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitHeight
+                : phonePortraitWidth;
+        final int phoneHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitWidth
+                : phonePortraitHeight;
+
+        // Minimum layout requirements.
+        final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth;
+        final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
+
+        // Final result.
+        final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth));
+        final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight));
+
+        bounds.set(0, 0, width, height);
+    }
+
+    /**
+     * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds
+     * centers at its center or display's center if inOutBounds is empty.
+     */
+    private void centerBounds(@NonNull ActivityDisplay display, int width, int height,
+            @NonNull Rect inOutBounds) {
+        if (inOutBounds.isEmpty()) {
+            display.getBounds(inOutBounds);
+        }
+        final int left = inOutBounds.centerX() - width / 2;
+        final int top = inOutBounds.centerY() - height / 2;
+        inOutBounds.set(left, top, left + width, top + height);
+    }
+
+    private void adjustBoundsToFitInDisplay(@NonNull ActivityDisplay display,
+            @NonNull Rect inOutBounds) {
+        final Rect displayBounds = display.getBounds();
+
+        if (displayBounds.width() < inOutBounds.width()
+                || displayBounds.height() < inOutBounds.height()) {
+            // There is no way for us to fit the bounds in the display without changing width
+            // or height. Don't even try it.
+            return;
+        }
+
+        final int dx;
+        if (inOutBounds.right > displayBounds.right) {
+            // Right edge is out of display.
+            dx = displayBounds.right - inOutBounds.right;
+        } else if (inOutBounds.left < displayBounds.left) {
+            // Left edge is out of display.
+            dx = displayBounds.left - inOutBounds.left;
+        } else {
+            // Vertical edges are all in display.
+            dx = 0;
+        }
+
+        final int dy;
+        if (inOutBounds.top < displayBounds.top) {
+            // Top edge is out of display.
+            dy = displayBounds.top - inOutBounds.top;
+        } else if (inOutBounds.bottom > displayBounds.bottom) {
+            // Bottom edge is out of display.
+            dy = displayBounds.bottom - inOutBounds.bottom;
+        } else {
+            // Horizontal edges are all in display.
+            dy = 0;
+        }
+        inOutBounds.offset(dx, dy);
+    }
+
+    /**
+     * Adjusts input bounds to avoid conflict with existing tasks in the display.
+     *
+     * If the input bounds conflict with existing tasks, this method scans the bounds in a series of
+     * directions to find a location where the we can put the bounds in display without conflict
+     * with any other tasks.
+     *
+     * It doesn't try to adjust bounds that's not fully in the given display.
+     *
+     * @param display the display which tasks are to check
+     * @param inOutBounds the bounds used to input initial bounds and output result bounds
+     */
+    private void adjustBoundsToAvoidConflict(@NonNull ActivityDisplay display,
+            @NonNull Rect inOutBounds) {
+        final Rect displayBounds = display.getBounds();
+        if (!displayBounds.contains(inOutBounds)) {
+            // The initial bounds are already out of display. The scanning algorithm below doesn't
+            // work so well with them.
+            return;
+        }
+
+        final List<TaskRecord> tasksToCheck = new ArrayList<>();
+        for (int i = 0; i < display.getChildCount(); ++i) {
+            ActivityStack<?> stack = display.getChildAt(i);
+            if (!stack.inFreeformWindowingMode()) {
+                continue;
+            }
+
+            for (int j = 0; j < stack.getChildCount(); ++j) {
+                tasksToCheck.add(stack.getChildAt(j));
+            }
+        }
+
+        if (!boundsConflict(tasksToCheck, inOutBounds)) {
+            // Current proposal doesn't conflict with any task. Early return to avoid unnecessary
+            // calculation.
+            return;
+        }
+
+        calculateCandidateShiftDirections(displayBounds, inOutBounds);
+        for (int direction : mTmpDirections) {
+            if (direction == Gravity.NO_GRAVITY) {
+                // We exhausted candidate directions, give up.
+                break;
+            }
+
+            mTmpBounds.set(inOutBounds);
+            while (boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+                shiftBounds(direction, displayBounds, mTmpBounds);
+            }
+
+            if (!boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+                // Found a candidate. Just use this.
+                inOutBounds.set(mTmpBounds);
+                if (DEBUG) appendLog("avoid-bounds-conflict=" + inOutBounds);
+                return;
+            }
+
+            // Didn't find a conflict free bounds here. Try the next candidate direction.
+        }
+
+        // We failed to find a conflict free location. Just keep the original result.
+    }
+
+    /**
+     * Determines scanning directions and their priorities to avoid bounds conflict.
+     *
+     * @param availableBounds bounds that the result must be in
+     * @param initialBounds initial bounds when start scanning
+     */
+    private void calculateCandidateShiftDirections(@NonNull Rect availableBounds,
+            @NonNull Rect initialBounds) {
+        for (int i = 0; i < mTmpDirections.length; ++i) {
+            mTmpDirections[i] = Gravity.NO_GRAVITY;
+        }
+
+        final int oneThirdWidth = (2 * availableBounds.left + availableBounds.right) / 3;
+        final int twoThirdWidth = (availableBounds.left + 2 * availableBounds.right) / 3;
+        final int centerX = initialBounds.centerX();
+        if (centerX < oneThirdWidth) {
+            // Too close to left, just scan to the right.
+            mTmpDirections[0] = Gravity.RIGHT;
+            return;
+        } else if (centerX > twoThirdWidth) {
+            // Too close to right, just scan to the left.
+            mTmpDirections[0] = Gravity.LEFT;
+            return;
+        }
+
+        final int oneThirdHeight = (2 * availableBounds.top + availableBounds.bottom) / 3;
+        final int twoThirdHeight = (availableBounds.top + 2 * availableBounds.bottom) / 3;
+        final int centerY = initialBounds.centerY();
+        if (centerY < oneThirdHeight || centerY > twoThirdHeight) {
+            // Too close to top or bottom boundary and we're in the middle horizontally, scan
+            // horizontally in both directions.
+            mTmpDirections[0] = Gravity.RIGHT;
+            mTmpDirections[1] = Gravity.LEFT;
+            return;
+        }
+
+        // We're in the center region both horizontally and vertically. Scan in both directions of
+        // primary diagonal.
+        mTmpDirections[0] = Gravity.BOTTOM | Gravity.RIGHT;
+        mTmpDirections[1] = Gravity.TOP | Gravity.LEFT;
+    }
+
+    private boolean boundsConflict(@NonNull List<TaskRecord> tasks, @NonNull Rect bounds) {
+        for (TaskRecord task : tasks) {
+            final Rect taskBounds = task.getBounds();
+            final boolean leftClose = Math.abs(taskBounds.left - bounds.left)
+                    < BOUNDS_CONFLICT_THRESHOLD;
+            final boolean topClose = Math.abs(taskBounds.top - bounds.top)
+                    < BOUNDS_CONFLICT_THRESHOLD;
+            final boolean rightClose = Math.abs(taskBounds.right - bounds.right)
+                    < BOUNDS_CONFLICT_THRESHOLD;
+            final boolean bottomClose = Math.abs(taskBounds.bottom - bounds.bottom)
+                    < BOUNDS_CONFLICT_THRESHOLD;
+
+            if ((leftClose && topClose) || (leftClose && bottomClose) || (rightClose && topClose)
+                    || (rightClose && bottomClose)) {
+                return true;
+            }
+        }
+
         return false;
     }
 
-    private static final boolean closeLeftTopCorner(Rect first, Rect second) {
-        return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
-                && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    private void shiftBounds(int direction, @NonNull Rect availableRect,
+            @NonNull Rect inOutBounds) {
+        final int horizontalOffset;
+        switch (direction & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.LEFT:
+                horizontalOffset = -Math.max(MINIMAL_STEP,
+                        availableRect.width() / STEP_DENOMINATOR);
+                break;
+            case Gravity.RIGHT:
+                horizontalOffset = Math.max(MINIMAL_STEP, availableRect.width() / STEP_DENOMINATOR);
+                break;
+            default:
+                horizontalOffset = 0;
+        }
+
+        final int verticalOffset;
+        switch (direction & Gravity.VERTICAL_GRAVITY_MASK) {
+            case Gravity.TOP:
+                verticalOffset = -Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
+                break;
+            case Gravity.BOTTOM:
+                verticalOffset = Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
+                break;
+            default:
+                verticalOffset = 0;
+        }
+
+        inOutBounds.offset(horizontalOffset, verticalOffset);
     }
 
-    private static final boolean closeRightTopCorner(Rect first, Rect second) {
-        return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
-                && Math.abs(first.top - second.top) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    private void initLogBuilder(TaskRecord task, ActivityRecord activity) {
+        if (DEBUG) {
+            mLogBuilder = new StringBuilder("TaskLaunchParamsModifier:task=" + task
+                    + " activity=" + activity);
+        }
     }
 
-    private static final boolean closeLeftBottomCorner(Rect first, Rect second) {
-        return Math.abs(first.left - second.left) < BOUNDS_CONFLICT_MIN_DISTANCE
-                && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    private void appendLog(String log) {
+        if (DEBUG) mLogBuilder.append(" ").append(log);
     }
 
-    private static final boolean closeRightBottomCorner(Rect first, Rect second) {
-        return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
-                && Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
+    private void outputLog() {
+        if (DEBUG) Slog.d(TAG, mLogBuilder.toString());
+    }
+
+    private static int orientationFromBounds(Rect bounds) {
+        return bounds.width() > bounds.height() ? SCREEN_ORIENTATION_LANDSCAPE
+                : SCREEN_ORIENTATION_PORTRAIT;
+    }
+
+    private static boolean sizeMatches(Rect left, Rect right) {
+        return (Math.abs(right.width() - left.width()) < EPSILON)
+                && (Math.abs(right.height() - left.height()) < EPSILON);
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ca9b256..30659c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -1031,6 +1031,11 @@
                 result.isPortal() /* isCaptivePortal */,
                 startTime, endTime);
 
+        log("isCaptivePortal: isSuccessful()=" + result.isSuccessful() +
+                " isPortal()=" + result.isPortal() +
+                " RedirectUrl=" + result.redirectUrl +
+                " StartTime=" + startTime + " EndTime=" + endTime);
+
         return result;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index b7bbd42..47e85b5 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -16,6 +16,12 @@
 
 package com.android.server.connectivity;
 
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_HOST;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PAC;
+import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PORT;
+import static android.provider.Settings.Global.HTTP_PROXY;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
@@ -47,16 +53,14 @@
     @NonNull
     private final Context mContext;
 
-    // TODO : make this private and import as much managing logic from ConnectivityService as
-    // possible
     @NonNull
-    public final Object mProxyLock = new Object();
+    private final Object mProxyLock = new Object();
     // The global proxy is the proxy that is set device-wide, overriding any network-specific
     // proxy. Note however that proxies are hints ; the system does not enforce their use. Hence
     // this value is only for querying.
     @Nullable
     @GuardedBy("mProxyLock")
-    public ProxyInfo mGlobalProxy = null;
+    private ProxyInfo mGlobalProxy = null;
     // The default proxy is the proxy that applies to no particular network if the global proxy
     // is not set. Individual networks have their own settings that override this. This member
     // is set through setDefaultProxy, which is called when the default network changes proxies
@@ -64,10 +68,10 @@
     // when PacManager resolves the proxy.
     @Nullable
     @GuardedBy("mProxyLock")
-    public volatile ProxyInfo mDefaultProxy = null;
-    // Whether the default proxy is disabled. TODO : make this mDefaultProxyEnabled
+    private volatile ProxyInfo mDefaultProxy = null;
+    // Whether the default proxy is enabled.
     @GuardedBy("mProxyLock")
-    public boolean mDefaultProxyDisabled = false;
+    private boolean mDefaultProxyEnabled = true;
 
     // The object responsible for Proxy Auto Configuration (PAC).
     @NonNull
@@ -85,7 +89,7 @@
     @Nullable
     private static ProxyInfo canonicalizeProxyInfo(@Nullable final ProxyInfo proxy) {
         if (proxy != null && TextUtils.isEmpty(proxy.getHost())
-                && (proxy.getPacFileUrl() == null || Uri.EMPTY.equals(proxy.getPacFileUrl()))) {
+                && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
             return null;
         }
         return proxy;
@@ -123,7 +127,7 @@
         // This information is already available as a world read/writable jvm property.
         synchronized (mProxyLock) {
             final ProxyInfo ret = mGlobalProxy;
-            if ((ret == null) && !mDefaultProxyDisabled) return mDefaultProxy;
+            if ((ret == null) && mDefaultProxyEnabled) return mDefaultProxy;
             return ret;
         }
     }
@@ -146,11 +150,10 @@
      */
     public void loadGlobalProxy() {
         ContentResolver res = mContext.getContentResolver();
-        String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
-        int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
-        String exclList = Settings.Global.getString(res,
-                Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
-        String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
+        String host = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_HOST);
+        int port = Settings.Global.getInt(res, GLOBAL_HTTP_PROXY_PORT, 0);
+        String exclList = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+        String pacFileUrl = Settings.Global.getString(res, GLOBAL_HTTP_PROXY_PAC);
         if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
             ProxyInfo proxyProperties;
             if (!TextUtils.isEmpty(pacFileUrl)) {
@@ -167,10 +170,36 @@
                 mGlobalProxy = proxyProperties;
             }
         }
+        loadDeprecatedGlobalHttpProxy();
         // TODO : shouldn't this function call mPacManager.setCurrentProxyScriptUrl ?
     }
 
     /**
+     * Read the global proxy from the deprecated Settings.Global.HTTP_PROXY setting and apply it.
+     */
+    public void loadDeprecatedGlobalHttpProxy() {
+        final String proxy = Settings.Global.getString(mContext.getContentResolver(), HTTP_PROXY);
+        if (!TextUtils.isEmpty(proxy)) {
+            String data[] = proxy.split(":");
+            if (data.length == 0) {
+                return;
+            }
+
+            final String proxyHost = data[0];
+            int proxyPort = 8080;
+            if (data.length > 1) {
+                try {
+                    proxyPort = Integer.parseInt(data[1]);
+                } catch (NumberFormatException e) {
+                    return;
+                }
+            }
+            final ProxyInfo p = new ProxyInfo(proxyHost, proxyPort, "");
+            setGlobalProxy(p);
+        }
+    }
+
+    /**
      * Sends the system broadcast informing apps about a new proxy configuration.
      *
      * Confusingly this method also sets the PAC file URL. TODO : separate this, it has nothing
@@ -232,11 +261,10 @@
             final ContentResolver res = mContext.getContentResolver();
             final long token = Binder.clearCallingIdentity();
             try {
-                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, host);
-                Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, port);
-                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
-                        exclList);
-                Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
+                Settings.Global.putString(res, GLOBAL_HTTP_PROXY_HOST, host);
+                Settings.Global.putInt(res, GLOBAL_HTTP_PROXY_PORT, port);
+                Settings.Global.putString(res, GLOBAL_HTTP_PROXY_EXCLUSION_LIST, exclList);
+                Settings.Global.putString(res, GLOBAL_HTTP_PROXY_PAC, pacFileUrl);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -253,10 +281,7 @@
      */
     public void setDefaultProxy(@Nullable ProxyInfo proxyInfo) {
         synchronized (mProxyLock) {
-            if (mDefaultProxy != null && mDefaultProxy.equals(proxyInfo)) {
-                return;
-            }
-            if (mDefaultProxy == proxyInfo) return; // catches repeated nulls
+            if (Objects.equals(mDefaultProxy, proxyInfo)) return;
             if (proxyInfo != null &&  !proxyInfo.isValid()) {
                 if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
                 return;
@@ -277,9 +302,27 @@
             mDefaultProxy = proxyInfo;
 
             if (mGlobalProxy != null) return;
-            if (!mDefaultProxyDisabled) {
+            if (mDefaultProxyEnabled) {
                 sendProxyBroadcast(proxyInfo);
             }
         }
     }
+
+    /**
+     * Enable or disable the default proxy.
+     *
+     * This sets the flag for enabling/disabling the default proxy and sends the broadcast
+     * if applicable.
+     * @param enabled whether the default proxy should be enabled.
+     */
+    public void setDefaultProxyEnabled(final boolean enabled) {
+        synchronized (mProxyLock) {
+            if (mDefaultProxyEnabled != enabled) {
+                mDefaultProxyEnabled = enabled;
+                if (mGlobalProxy == null && mDefaultProxy != null) {
+                    sendProxyBroadcast(enabled ? mDefaultProxy : null);
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 71c419f..a9b0d5c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -421,7 +421,6 @@
         final IInputContext inputContext;
         final int uid;
         final int pid;
-        final int selfReportedDisplayId;
         final InputBinding binding;
         final ClientDeathRecipient clientDeathRecipient;
 
@@ -431,18 +430,16 @@
         @Override
         public String toString() {
             return "ClientState{" + Integer.toHexString(
-                    System.identityHashCode(this)) + " uid=" + uid
-                    + " pid=" + pid + " displayId=" + selfReportedDisplayId + "}";
+                    System.identityHashCode(this)) + " uid " + uid
+                    + " pid " + pid + "}";
         }
 
         ClientState(IInputMethodClient _client, IInputContext _inputContext,
-                int _uid, int _pid, int _selfReportedDisplayId,
-                ClientDeathRecipient _clientDeathRecipient) {
+                int _uid, int _pid, ClientDeathRecipient _clientDeathRecipient) {
             client = _client;
             inputContext = _inputContext;
             uid = _uid;
             pid = _pid;
-            selfReportedDisplayId = _selfReportedDisplayId;
             binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
             clientDeathRecipient = _clientDeathRecipient;
         }
@@ -1748,21 +1745,15 @@
      *               process
      * @param inputContext communication channel for the dummy
      *                     {@link android.view.inputmethod.InputConnection}
-     * @param selfReportedDisplayId self-reported display ID to which the client is associated.
-     *                              Whether the client is still allowed to access to this display
-     *                              or not needs to be evaluated every time the client interacts
-     *                              with the display
      */
     @Override
-    public void addClient(IInputMethodClient client, IInputContext inputContext,
-            int selfReportedDisplayId) {
+    public void addClient(IInputMethodClient client, IInputContext inputContext) {
         final int callerUid = Binder.getCallingUid();
         final int callerPid = Binder.getCallingPid();
         synchronized (mMethodMap) {
             // TODO: Optimize this linear search.
             for (ClientState state : mClients.values()) {
-                if (state.uid == callerUid && state.pid == callerPid
-                        && state.selfReportedDisplayId == selfReportedDisplayId) {
+                if (state.uid == callerUid && state.pid == callerPid) {
                     throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid
                             + " is already registered");
                 }
@@ -1773,25 +1764,11 @@
             } catch (RemoteException e) {
                 throw new IllegalStateException(e);
             }
-            // We cannot fully avoid race conditions where the client UID already lost the access to
-            // the given self-reported display ID, even if the client is not maliciously reporting
-            // a fake display ID. Unconditionally returning SecurityException just because the
-            // client doesn't pass display ID verification can cause many test failures hence not an
-            // option right now.  At the same time
-            //    context.getSystemService(InputMethodManager.class)
-            // is expected to return a valid non-null instance at any time if we do not choose to
-            // have the client crash.  Thus we do not verify the display ID at all here.  Instead we
-            // later check the display ID every time the client needs to interact with the specified
-            // display.
-            mClients.put(client.asBinder(), new ClientState(client, inputContext, callerUid,
-                    callerPid, selfReportedDisplayId, deathRecipient));
+            mClients.put(client.asBinder(),
+                    new ClientState(client, inputContext, callerUid, callerPid, deathRecipient));
         }
     }
 
-    private boolean verifyDisplayId(ClientState cs) {
-        return mWindowManagerInternal.isUidAllowedOnDisplay(cs.selfReportedDisplayId, cs.uid);
-    }
-
     void removeClient(IInputMethodClient client) {
         synchronized (mMethodMap) {
             ClientState cs = mClients.remove(client.asBinder());
@@ -1941,9 +1918,8 @@
         mCurAttribute = attribute;
 
         // Check if the input method is changing.
-        // We expect the caller has already verified that the client is allowed to access this
-        // display ID.
-        final int displayId = mCurFocusedWindowClient.selfReportedDisplayId;
+        final int displayId = mWindowManagerInternal.getDisplayIdForWindow(
+                mCurFocusedWindow);
         if (mCurId != null && mCurId.equals(mCurMethodId) && displayId == mCurTokenDisplayId) {
             if (cs.curSession != null) {
                 // Fast case: if we are already connected to the input method,
@@ -2008,11 +1984,7 @@
                 com.android.internal.R.string.input_method_binding_label);
         mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                 mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
-        if (!verifyDisplayId(mCurFocusedWindowClient)) {
-            // Wait, the client no longer has access to the display.
-            return InputBindResult.INVALID_DISPLAY_ID;
-        }
-        final int displayId = mCurFocusedWindowClient.selfReportedDisplayId;
+        final int displayId = mWindowManagerInternal.getDisplayIdForWindow(mCurFocusedWindow);
         mCurTokenDisplayId = (displayId != INVALID_DISPLAY) ? displayId : DEFAULT_DISPLAY;
 
         if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) {
@@ -2612,8 +2584,7 @@
                     if (cs == null) {
                         throw new IllegalArgumentException("unknown client " + client.asBinder());
                     }
-                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                            cs.selfReportedDisplayId)) {
+                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                         Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
                         return false;
                     }
@@ -2697,8 +2668,7 @@
                     if (cs == null) {
                         throw new IllegalArgumentException("unknown client " + client.asBinder());
                     }
-                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                            cs.selfReportedDisplayId)) {
+                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                         if (DEBUG) {
                             Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
                         }
@@ -2797,8 +2767,6 @@
         InputBindResult res = null;
         long ident = Binder.clearCallingIdentity();
         try {
-            final int windowDisplayId =
-                    mWindowManagerInternal.getDisplayIdForWindow(windowToken);
             synchronized (mMethodMap) {
                 if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason="
                         + InputMethodClient.getStartInputReason(startInputReason)
@@ -2817,15 +2785,8 @@
                     throw new IllegalArgumentException("unknown client "
                             + client.asBinder());
                 }
-                if (cs.selfReportedDisplayId != windowDisplayId) {
-                    Slog.e(TAG, "startInputOrWindowGainedFocusInternal: display ID mismatch."
-                            + " from client:" + cs.selfReportedDisplayId
-                            + " from window:" + windowDisplayId);
-                    return InputBindResult.DISPLAY_ID_MISMATCH;
-                }
 
-                if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                        cs.selfReportedDisplayId)) {
+                if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid)) {
                     // Check with the window manager to make sure this client actually
                     // has a window with focus.  If not, reject.  This is thread safe
                     // because if the focus changes some time before or after, the
@@ -2897,9 +2858,9 @@
                                 // If focused display changed, we should unbind current method
                                 // to make app window in previous display relayout after Ime
                                 // window token removed.
-                                // Note that we can trust client's display ID as long as it matches
-                                // to the display ID obtained from the window.
-                                if (cs.selfReportedDisplayId != mCurTokenDisplayId) {
+                                final int newFocusDisplayId =
+                                        mWindowManagerInternal.getDisplayIdForWindow(windowToken);
+                                if (newFocusDisplayId != mCurTokenDisplayId) {
                                     unbindCurrentMethodLocked();
                                 }
                             }
@@ -2997,7 +2958,6 @@
     }
 
     private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
-        // TODO(yukawa): multi-display support.
         final int uid = Binder.getCallingUid();
         if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
             return true;
@@ -3074,7 +3034,6 @@
     @Override
     public void showInputMethodAndSubtypeEnablerFromClient(
             IInputMethodClient client, String inputMethodId) {
-        // TODO(yukawa): Should we verify the display ID?
         if (!calledFromValidUser()) {
             return;
         }
@@ -3270,7 +3229,6 @@
      */
     @Override
     public int getInputMethodWindowVisibleHeight() {
-        // TODO(yukawa): Should we verify the display ID?
         return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
     }
 
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 9640e04..b29b7cf 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -76,6 +76,13 @@
      */
     private final AtomicBoolean mConnectionOpen = new AtomicBoolean(true);
 
+    /*
+     * Internal interface used to invoke client callbacks.
+     */
+    private interface CallbackConsumer {
+        void accept(IContextHubClientCallback callback) throws RemoteException;
+    }
+
     /* package */ ContextHubClientBroker(
             Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
             int contextHubId, short hostEndPointId, IContextHubClientCallback callback) {
@@ -140,12 +147,9 @@
     /**
      * Invoked when the underlying binder of this broker has died at the client process.
      */
+    @Override
     public void binderDied() {
-        try {
-            IContextHubClient.Stub.asInterface(this).close();
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException while closing client on death", e);
-        }
+        close();
     }
 
     /**
@@ -168,14 +172,7 @@
      * @param message the message that came from a nanoapp
      */
     /* package */ void sendMessageToClient(NanoAppMessage message) {
-        if (mConnectionOpen.get()) {
-            try {
-                mCallbackInterface.onMessageFromNanoApp(message);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException while sending message to client (host endpoint ID = "
-                        + mHostEndPointId + ")", e);
-            }
-        }
+        invokeCallbackConcurrent(callback -> callback.onMessageFromNanoApp(message));
     }
 
     /**
@@ -184,14 +181,7 @@
      * @param nanoAppId the ID of the nanoapp that was loaded.
      */
     /* package */ void onNanoAppLoaded(long nanoAppId) {
-        if (mConnectionOpen.get()) {
-            try {
-                mCallbackInterface.onNanoAppLoaded(nanoAppId);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException while calling onNanoAppLoaded on client"
-                        + " (host endpoint ID = " + mHostEndPointId + ")", e);
-            }
-        }
+        invokeCallbackConcurrent(callback -> callback.onNanoAppLoaded(nanoAppId));
     }
 
     /**
@@ -200,28 +190,14 @@
      * @param nanoAppId the ID of the nanoapp that was unloaded.
      */
     /* package */ void onNanoAppUnloaded(long nanoAppId) {
-        if (mConnectionOpen.get()) {
-            try {
-                mCallbackInterface.onNanoAppUnloaded(nanoAppId);
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException while calling onNanoAppUnloaded on client"
-                        + " (host endpoint ID = " + mHostEndPointId + ")", e);
-            }
-        }
+        invokeCallbackConcurrent(callback -> callback.onNanoAppUnloaded(nanoAppId));
     }
 
     /**
      * Notifies the client of a hub reset event if the connection is open.
      */
     /* package */ void onHubReset() {
-        if (mConnectionOpen.get()) {
-            try {
-                mCallbackInterface.onHubReset();
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException while calling onHubReset on client" +
-                        " (host endpoint ID = " + mHostEndPointId + ")", e);
-            }
-        }
+        invokeCallbackConcurrent(callback -> callback.onHubReset());
     }
 
     /**
@@ -231,12 +207,21 @@
      * @param abortCode the nanoapp specific abort code
      */
     /* package */ void onNanoAppAborted(long nanoAppId, int abortCode) {
+        invokeCallbackConcurrent(callback -> callback.onNanoAppAborted(nanoAppId, abortCode));
+    }
+
+    /**
+     * Helper function to invoke a specified client callback, if the connection is open.
+     *
+     * @param consumer the consumer specifying the callback to invoke
+     */
+    private void invokeCallbackConcurrent(CallbackConsumer consumer) {
         if (mConnectionOpen.get()) {
             try {
-                mCallbackInterface.onNanoAppAborted(nanoAppId, abortCode);
+                consumer.accept(mCallbackInterface);
             } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException while calling onNanoAppAborted on client"
-                        + " (host endpoint ID = " + mHostEndPointId + ")", e);
+                Log.e(TAG, "RemoteException while invoking client callback (host endpoint ID = "
+                        + mHostEndPointId + ")", e);
             }
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f9d49d7..506cc44 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4282,14 +4282,16 @@
     }
 
     private void doChannelWarningToast(CharSequence toastText) {
-        final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
-        final boolean warningEnabled = Settings.Global.getInt(getContext().getContentResolver(),
-                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
-        if (warningEnabled) {
-            Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
-                    Toast.LENGTH_SHORT);
-            toast.show();
-        }
+        Binder.withCleanCallingIdentity(() -> {
+            final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
+            final boolean warningEnabled = Settings.Global.getInt(getContext().getContentResolver(),
+                    Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
+            if (warningEnabled) {
+                Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
+                        Toast.LENGTH_SHORT);
+                toast.show();
+            }
+        });
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
index 3ffc5c5..9c1ac34 100644
--- a/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
+++ b/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@@ -57,7 +57,7 @@
             // should use the getSerialForPackage method with the calling package specified.
             if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
                     /* callingPackage */ null, "getSerial")) {
-                return null;
+                return Build.UNKNOWN;
             }
             return SystemProperties.get("ro.serialno", Build.UNKNOWN);
         }
@@ -66,7 +66,7 @@
         public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
             if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
                     callingPackage, "getSerial")) {
-                return null;
+                return Build.UNKNOWN;
             }
             return SystemProperties.get("ro.serialno", Build.UNKNOWN);
         }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 9323040..a08c189 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -20,6 +20,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AppDetailsActivity;
 import android.app.AppGlobals;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
@@ -65,7 +66,9 @@
 import com.android.server.SystemService;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 
 /**
@@ -74,6 +77,7 @@
  */
 public class LauncherAppsService extends SystemService {
 
+    private static final boolean SHOW_HIDDEN_APP_ENABLED = false;
     private final LauncherAppsImpl mLauncherAppsImpl;
 
     public LauncherAppsService(Context context) {
@@ -281,15 +285,84 @@
             }
         }
 
+        private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
+                UserHandle user) {
+            Intent intent = new Intent();
+            intent.setComponent(new ComponentName(packageName, AppDetailsActivity.class.getName()));
+            final PackageManagerInternal pmInt =
+                    LocalServices.getService(PackageManagerInternal.class);
+            List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                    callingUid, user.getIdentifier());
+            if (apps.size() > 0) {
+                return apps.get(0);
+            }
+            return null;
+        }
+
         @Override
         public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
-                String packageName, UserHandle user)
-                throws RemoteException {
-            return queryActivitiesForUser(callingPackage,
+                String packageName, UserHandle user) throws RemoteException {
+            ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser(
+                    callingPackage,
                     new Intent(Intent.ACTION_MAIN)
                             .addCategory(Intent.CATEGORY_LAUNCHER)
                             .setPackage(packageName),
                     user);
+            if (!SHOW_HIDDEN_APP_ENABLED) {
+                return launcherActivities;
+            }
+
+            final int callingUid = injectBinderCallingUid();
+            final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
+            if (packageName != null) {
+                // If target package has launcher activities, then return those launcher
+                // activities. Otherwise, return hidden activity that forwards user to app
+                // details page.
+                if (result.size() > 0) {
+                    return launcherActivities;
+                }
+                ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
+                if (info != null) {
+                    result.add(info);
+                }
+                return new ParceledListSlice<>(result);
+            }
+
+            long ident = injectClearCallingIdentity();
+            try {
+                final HashSet<String> visiblePackages = new HashSet<>();
+                for (ResolveInfo info : result) {
+                    visiblePackages.add(info.activityInfo.packageName);
+                }
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
+                        user.getIdentifier(), callingUid);
+                for (ApplicationInfo applicationInfo : installedPackages) {
+                    if (!visiblePackages.contains(applicationInfo.packageName)) {
+                        if (!shouldShowHiddenApp(applicationInfo)) {
+                            continue;
+                        }
+                        ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName,
+                                callingUid, user);
+                        if (info != null) {
+                            result.add(info);
+                        }
+                    }
+                }
+                return new ParceledListSlice<>(result);
+            } finally {
+                injectRestoreCallingIdentity(ident);
+            }
+        }
+
+        private static boolean shouldShowHiddenApp(ApplicationInfo appInfo) {
+            if (appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
+                return false;
+            }
+            return true;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13f084e..1180af8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -121,6 +121,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.AppDetailsActivity;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.ResourcesManager;
@@ -187,6 +188,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
@@ -2920,7 +2922,7 @@
                 for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
                     final PermissionManager.SplitPermissionInfo splitPerm =
                             splitPermissions.get(splitPermNum);
-                    final String rootPerm = splitPerm.getRootPermission();
+                    final String rootPerm = splitPerm.getSplitPermission();
 
                     if (preUpgradeSdkVersion >= splitPerm.getTargetSdk()) {
                         continue;
@@ -2942,11 +2944,11 @@
                             continue;
                         }
 
-                        final String[] newPerms = splitPerm.getNewPermissions();
+                        final List<String> newPerms = splitPerm.getNewPermissions();
 
-                        final int numNewPerms = newPerms.length;
+                        final int numNewPerms = newPerms.size();
                         for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
-                            final String newPerm = newPerms[newPermNum];
+                            final String newPerm = newPerms.get(newPermNum);
                             if (checkPermission(newPerm, pkgName, userId) == PERMISSION_GRANTED) {
                                 continue;
                             }
@@ -7869,10 +7871,16 @@
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
         final int callingUid = Binder.getCallingUid();
+        return new ParceledListSlice<>(
+                getInstalledApplicationsListInternal(flags, userId, callingUid));
+    }
+
+    private List<ApplicationInfo> getInstalledApplicationsListInternal(int flags, int userId,
+            int callingUid) {
         if (getInstantAppPackageName(callingUid) != null) {
-            return ParceledListSlice.emptyList();
+            return Collections.emptyList();
         }
-        if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
+        if (!sUserManager.exists(userId)) return Collections.emptyList();
         flags = updateFlagsForApplication(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
 
@@ -7937,7 +7945,7 @@
                 }
             }
 
-            return new ParceledListSlice<>(list);
+            return list;
         }
     }
 
@@ -12150,7 +12158,9 @@
             if (mPackageListObservers.size() == 0) {
                 return;
             }
-            observers = (PackageListObserver[]) mPackageListObservers.toArray();
+            final PackageListObserver[] observerArray =
+                    new PackageListObserver[mPackageListObservers.size()];
+            observers = mPackageListObservers.toArray(observerArray);
         }
         for (int i = observers.length - 1; i >= 0; --i) {
             observers[i].onPackageAdded(packageName);
@@ -12170,7 +12180,9 @@
             if (mPackageListObservers.size() == 0) {
                 return;
             }
-            observers = (PackageListObserver[]) mPackageListObservers.toArray();
+            final PackageListObserver[] observerArray =
+                    new PackageListObserver[mPackageListObservers.size()];
+            observers = mPackageListObservers.toArray(observerArray);
         }
         for (int i = observers.length - 1; i >= 0; --i) {
             observers[i].onPackageRemoved(packageName);
@@ -12705,8 +12717,8 @@
 
     @Override
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
-            PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage,
-            String callingPackage, int userId) {
+            PersistableBundle appExtras, PersistableBundle launcherExtras,
+            SuspendDialogInfo dialogInfo, String callingPackage, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
                 "setPackagesSuspendedAsUser");
 
@@ -12751,7 +12763,7 @@
                         unactionedPackages.add(packageName);
                         continue;
                     }
-                    pkgSetting.setSuspended(suspended, callingPackage, dialogMessage, appExtras,
+                    pkgSetting.setSuspended(suspended, callingPackage, dialogInfo, appExtras,
                             launcherExtras, userId);
                     changedPackagesList.add(packageName);
                     changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
@@ -17805,7 +17817,7 @@
                     false /*hidden*/,
                     false /*suspended*/,
                     null /*suspendingPackage*/,
-                    null /*dialogMessage*/,
+                    null /*dialogInfo*/,
                     null /*suspendedAppExtras*/,
                     null /*suspendedLauncherExtras*/,
                     false /*instantApp*/,
@@ -19388,6 +19400,16 @@
                 throw new SecurityException("Cannot disable a protected package: " + packageName);
             }
         }
+        // Only allow apps with CHANGE_COMPONENT_ENABLED_STATE permission to change hidden
+        // app details activity
+        if (AppDetailsActivity.class.getName().equals(className)) {
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE)
+                    != PackageManager.PERMISSION_GRANTED) {
+                Slog.e(TAG, "Cannot disable a protected component: " + packageName);
+                return;
+            }
+        }
 
         synchronized (mPackages) {
             if (callingUid == Process.SHELL_UID
@@ -22283,6 +22305,14 @@
         }
 
         @Override
+        public List<ApplicationInfo> getInstalledApplications(int flags, int userId,
+                int callingUid) {
+            return PackageManagerService.this.getInstalledApplicationsListInternal(flags, userId,
+                    callingUid);
+        }
+
+
+        @Override
         public boolean isPlatformSigned(String packageName) {
             PackageSetting packageSetting = mSettings.mPackages.get(packageName);
             if (packageSetting == null) {
@@ -22556,10 +22586,10 @@
         }
 
         @Override
-        public String getSuspendedDialogMessage(String suspendedPackage, int userId) {
+        public SuspendDialogInfo getSuspendedDialogInfo(String suspendedPackage, int userId) {
             synchronized (mPackages) {
                 final PackageSetting ps = mSettings.mPackages.get(suspendedPackage);
-                return (ps != null) ? ps.readUserState(userId).dialogMessage : null;
+                return (ps != null) ? ps.readUserState(userId).dialogInfo : null;
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 93729d1..e25cca4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -51,6 +51,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
 import android.content.pm.dex.ArtManager;
@@ -1701,9 +1702,18 @@
         }
         final String callingPackage =
                 (Binder.getCallingUid() == Process.ROOT_UID) ? "root" : "com.android.shell";
+
+        final SuspendDialogInfo info;
+        if (!TextUtils.isEmpty(dialogMessage)) {
+            info = new SuspendDialogInfo.Builder()
+                    .setMessage(dialogMessage)
+                    .build();
+        } else {
+            info = null;
+        }
         try {
             mInterface.setPackagesSuspendedAsUser(new String[]{packageName}, suspendedState,
-                    appExtras, launcherExtras, dialogMessage, callingPackage, userId);
+                    appExtras, launcherExtras, info, callingPackage, userId);
             pw.println("Package " + packageName + " new suspended state: "
                     + mInterface.isPackageSuspendedForUser(packageName, userId));
             return 0;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index fd6aceb..3c22f07 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.Signature;
+import android.content.pm.SuspendDialogInfo;
 import android.os.PersistableBundle;
 import android.service.pm.PackageProto;
 import android.util.ArraySet;
@@ -395,12 +396,12 @@
         return readUserState(userId).suspended;
     }
 
-    void setSuspended(boolean suspended, String suspendingPackage, String dialogMessage,
+    void setSuspended(boolean suspended, String suspendingPackage, SuspendDialogInfo dialogInfo,
             PersistableBundle appExtras, PersistableBundle launcherExtras, int userId) {
         final PackageUserState existingUserState = modifyUserState(userId);
         existingUserState.suspended = suspended;
         existingUserState.suspendingPackage = suspended ? suspendingPackage : null;
-        existingUserState.dialogMessage = suspended ? dialogMessage : null;
+        existingUserState.dialogInfo = suspended ? dialogInfo : null;
         existingUserState.suspendedAppExtras = suspended ? appExtras : null;
         existingUserState.suspendedLauncherExtras = suspended ? launcherExtras : null;
     }
@@ -423,7 +424,7 @@
 
     void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
             boolean notLaunched, boolean hidden, boolean suspended, String suspendingPackage,
-            String dialogMessage, PersistableBundle suspendedAppExtras,
+            SuspendDialogInfo dialogInfo, PersistableBundle suspendedAppExtras,
             PersistableBundle suspendedLauncherExtras, boolean instantApp,
             boolean virtualPreload, String lastDisableAppCaller,
             ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
@@ -438,7 +439,7 @@
         state.hidden = hidden;
         state.suspended = suspended;
         state.suspendingPackage = suspendingPackage;
-        state.dialogMessage = dialogMessage;
+        state.dialogInfo = dialogInfo;
         state.suspendedAppExtras = suspendedAppExtras;
         state.suspendedLauncherExtras = suspendedLauncherExtras;
         state.lastDisableAppCaller = lastDisableAppCaller;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5c88e06..6a7e654 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -49,6 +49,7 @@
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.net.Uri;
@@ -203,6 +204,7 @@
     private static final String TAG_DEFAULT_BROWSER = "default-browser";
     private static final String TAG_DEFAULT_DIALER = "default-dialer";
     private static final String TAG_VERSION = "version";
+    private static final String TAG_SUSPENDED_DIALOG_INFO = "suspended-dialog-info";
     private static final String TAG_SUSPENDED_APP_EXTRAS = "suspended-app-extras";
     private static final String TAG_SUSPENDED_LAUNCHER_EXTRAS = "suspended-launcher-extras";
 
@@ -222,6 +224,10 @@
     private static final String ATTR_HIDDEN = "hidden";
     private static final String ATTR_SUSPENDED = "suspended";
     private static final String ATTR_SUSPENDING_PACKAGE = "suspending-package";
+    /**
+     * @deprecated Legacy attribute, kept only for upgrading from P builds.
+     */
+    @Deprecated
     private static final String ATTR_SUSPEND_DIALOG_MESSAGE = "suspend_dialog_message";
     // Legacy, uninstall blocks are stored separately.
     @Deprecated
@@ -730,7 +736,7 @@
                                 false /*hidden*/,
                                 false /*suspended*/,
                                 null /*suspendingPackage*/,
-                                null /*dialogMessage*/,
+                                null /*dialogInfo*/,
                                 null /*suspendedAppExtras*/,
                                 null /*suspendedLauncherExtras*/,
                                 instantApp,
@@ -1620,7 +1626,7 @@
                                 false /*hidden*/,
                                 false /*suspended*/,
                                 null /*suspendingPackage*/,
-                                null /*dialogMessage*/,
+                                null /*dialogInfo*/,
                                 null /*suspendedAppExtras*/,
                                 null /*suspendedLauncherExtras*/,
                                 false /*instantApp*/,
@@ -1730,6 +1736,7 @@
                     ArraySet<String> disabledComponents = null;
                     PersistableBundle suspendedAppExtras = null;
                     PersistableBundle suspendedLauncherExtras = null;
+                    SuspendDialogInfo suspendDialogInfo = null;
 
                     int packageDepth = parser.getDepth();
                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -1752,20 +1759,28 @@
                             case TAG_SUSPENDED_LAUNCHER_EXTRAS:
                                 suspendedLauncherExtras = PersistableBundle.restoreFromXml(parser);
                                 break;
+                            case TAG_SUSPENDED_DIALOG_INFO:
+                                suspendDialogInfo = SuspendDialogInfo.restoreFromXml(parser);
+                                break;
                             default:
                                 Slog.wtf(TAG, "Unknown tag " + parser.getName() + " under tag "
                                         + TAG_PACKAGE);
                         }
                     }
+                    if (suspendDialogInfo == null && !TextUtils.isEmpty(dialogMessage)) {
+                        suspendDialogInfo = new SuspendDialogInfo.Builder()
+                                .setMessage(dialogMessage)
+                                .build();
+                    }
 
                     if (blockUninstall) {
                         setBlockUninstallLPw(userId, name, true);
                     }
                     ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
-                            hidden, suspended, suspendingPackage, dialogMessage, suspendedAppExtras,
-                            suspendedLauncherExtras, instantApp, virtualPreload, enabledCaller,
-                            enabledComponents, disabledComponents, verifState, linkGeneration,
-                            installReason, harmfulAppWarning);
+                            hidden, suspended, suspendingPackage, suspendDialogInfo,
+                            suspendedAppExtras, suspendedLauncherExtras, instantApp, virtualPreload,
+                            enabledCaller, enabledComponents, disabledComponents, verifState,
+                            linkGeneration, installReason, harmfulAppWarning);
                 } else if (tagName.equals("preferred-activities")) {
                     readPreferredActivitiesLPw(parser, userId);
                 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -2076,9 +2091,10 @@
                         serializer.attribute(null, ATTR_SUSPENDING_PACKAGE,
                                 ustate.suspendingPackage);
                     }
-                    if (ustate.dialogMessage != null) {
-                        serializer.attribute(null, ATTR_SUSPEND_DIALOG_MESSAGE,
-                                ustate.dialogMessage);
+                    if (ustate.dialogInfo != null) {
+                        serializer.startTag(null, TAG_SUSPENDED_DIALOG_INFO);
+                        ustate.dialogInfo.saveToXml(serializer);
+                        serializer.endTag(null, TAG_SUSPENDED_DIALOG_INFO);
                     }
                     if (ustate.suspendedAppExtras != null) {
                         serializer.startTag(null, TAG_SUSPENDED_APP_EXTRAS);
@@ -4737,8 +4753,8 @@
                 final PackageUserState pus = ps.readUserState(user.id);
                 pw.print(" suspendingPackage=");
                 pw.print(pus.suspendingPackage);
-                pw.print(" dialogMessage=");
-                pw.print(pus.dialogMessage);
+                pw.print(" dialogInfo=");
+                pw.print(pus.dialogInfo);
             }
             pw.print(" stopped=");
             pw.print(ps.getStopped(user.id));
diff --git a/services/core/java/com/android/server/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
index ad52559..c93af2a 100644
--- a/services/core/java/com/android/server/pm/dex/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -1,19 +1,12 @@
 {
   "presubmit": [
     {
-      "name": "DexLoggerTests"
-    },
-    {
-      "name": "DexManagerTests"
-    },
-    {
-      "name": "DexoptOptionsTests"
-    },
-    {
-      "name": "DexoptUtilsTest"
-    },
-    {
-      "name": "PackageDexUsageTests"
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.pm.dex"
+        }
+      ]
     },
     {
       "name": "DexLoggerIntegrationTests"
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6f644dd..0a93653 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1033,8 +1033,8 @@
 
             if (applicationInfo != null
                     && applicationInfo.targetSdkVersion < splitPerm.getTargetSdk()
-                    && permissionsWithoutSplits.contains(splitPerm.getRootPermission())) {
-                Collections.addAll(permissions, splitPerm.getNewPermissions());
+                    && permissionsWithoutSplits.contains(splitPerm.getSplitPermission())) {
+                permissions.addAll(splitPerm.getNewPermissions());
             }
         }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 21bf488..06ee935 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6046,6 +6046,19 @@
             }
         }
 
+        // Intercept the Accessibility keychord (CTRL + ALT + Z) for keyboard users.
+        if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_Z: {
+                    if (down && event.isCtrlPressed() && event.isAltPressed()) {
+                        mHandler.sendMessage(mHandler.obtainMessage(MSG_ACCESSIBILITY_SHORTCUT));
+                        result &= ~ACTION_PASS_TO_USER;
+                    }
+                    break;
+                }
+            }
+        }
+
         if (useHapticFeedback) {
             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
                     "Virtual Key - Press");
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 1cba1c7..a55b49f 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -95,10 +95,22 @@
         mIsShowing = showing;
 
         mCallback.onShowingChanged();
-        try {
-            mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Error informing keystore of screen lock", e);
+        int retry = 2;
+        while (retry > 0) {
+            try {
+                mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
+                break;
+            } catch (RemoteException e) {
+                if (retry == 2) {
+                    Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died"
+                            + " -> refreshing service token and retrying");
+                    mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
+                            .getService("android.security.keystore"));
+                } else {
+                    Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e);
+                }
+                --retry;
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 1abaaf2..6ca4f2e 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1056,6 +1056,11 @@
             e.writeLong(entry.totalLatencyMicros);
             e.writeLong(entry.cpuUsageMicros);
             e.writeBoolean(entry.isInteractive);
+            e.writeLong(entry.maxCpuUsageMicros);
+            e.writeLong(entry.maxLatencyMicros);
+            e.writeLong(entry.recordedDelayMessageCount);
+            e.writeLong(entry.delayMillis);
+            e.writeLong(entry.maxDelayMillis);
             pulledData.add(e);
         }
     }
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index d36ab3f..5ce8145 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -28,7 +28,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.textclassifier.ITextClassificationCallback;
 import android.service.textclassifier.ITextClassifierService;
 import android.service.textclassifier.ITextLinksCallback;
@@ -41,7 +40,6 @@
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassificationSessionId;
-import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
 import android.view.textclassifier.TextSelection;
 
@@ -275,6 +273,20 @@
         IndentingPrintWriter pw = new IndentingPrintWriter(fout, "  ");
         TextClassificationManager tcm = mContext.getSystemService(TextClassificationManager.class);
         tcm.dump(pw);
+
+        pw.printPair("context", mContext); pw.println();
+        synchronized (mLock) {
+            int size = mUserStates.size();
+            pw.print("Number user states: "); pw.println(size);
+            if (size > 0) {
+                for (int i = 0; i < size; i++) {
+                    pw.increaseIndent();
+                    UserState userState = mUserStates.valueAt(i);
+                    pw.print(i); pw.print(":"); userState.dump(pw); pw.println();
+                    pw.decreaseIndent();
+                }
+            }
+        }
     }
 
     private static final class PendingRequest implements IBinder.DeathRecipient {
@@ -431,6 +443,15 @@
             return willBind;
         }
 
+        private void dump(IndentingPrintWriter pw) {
+            pw.printPair("context", mContext);
+            pw.printPair("userId", mUserId);
+            synchronized (mLock) {
+                pw.printPair("binding", mBinding);
+                pw.printPair("numberRequests", mPendingRequests.size());
+            }
+        }
+
         private final class TextClassifierServiceConnection implements ServiceConnection {
             @Override
             public void onServiceConnected(ComponentName name, IBinder service) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index e57fea3..e38e229 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -102,6 +102,7 @@
 import android.view.animation.Animation;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -1741,6 +1742,30 @@
         return boundsLayer;
     }
 
+    /** Get position and crop region of animation. */
+    @VisibleForTesting
+    void getAnimationBounds(Point outPosition, Rect outBounds) {
+        outPosition.set(0, 0);
+        outBounds.setEmpty();
+
+        final TaskStack stack = getStack();
+        final Task task = getTask();
+        if (task != null && task.inFreeformWindowingMode()) {
+            task.getRelativePosition(outPosition);
+        } else if (stack != null) {
+            stack.getRelativePosition(outPosition);
+        }
+
+        // Always use stack bounds in order to have the ability to animate outside the task region.
+        // It also needs to be consistent when {@link #mNeedsAnimationBoundsLayer} is set that crops
+        // according to the bounds.
+        if (stack != null) {
+            stack.getBounds(outBounds);
+        }
+        // We have the relative position so the local position can be removed from bounds.
+        outBounds.offsetTo(0, 0);
+    }
+
     boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
             boolean isVoiceInteraction) {
 
@@ -1759,14 +1784,7 @@
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
         if (okToAnimate()) {
             final AnimationAdapter adapter;
-            final TaskStack stack = getStack();
-            mTmpPoint.set(0, 0);
-            mTmpRect.setEmpty();
-            if (stack != null) {
-                stack.getRelativePosition(mTmpPoint);
-                stack.getBounds(mTmpRect);
-                mTmpRect.offsetTo(0, 0);
-            }
+            getAnimationBounds(mTmpPoint, mTmpRect);
 
             // Delaying animation start isn't compatible with remote animations at all.
             if (mService.mAppTransition.getRemoteAnimationController() != null
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6f728fc..642f5781 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -92,7 +92,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -119,7 +118,6 @@
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
 
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
@@ -2065,9 +2063,25 @@
         layoutAndAssignWindowLayersIfNeeded();
     }
 
-    int taskIdFromPoint(int x, int y) {
+    /**
+     * Used to obtain task ID when user taps on coordinate (x, y) in this display, and outside
+     * current task in focus.
+     *
+     * This returns the task ID of the foremost task at (x, y) if the task is not home. Otherwise it
+     * returns -1.
+     *
+     * @param x horizontal coordinate of the tap position
+     * @param y vertical coordinate of the tap position
+     * @return the task ID if a non-home task is found; -1 if not
+     */
+    int taskForTapOutside(int x, int y) {
         for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx);
+            if (stack.isActivityTypeHome()) {
+                // We skip not only home stack, but also everything behind home because user can't
+                // see them.
+                break;
+            }
             final int taskId = stack.taskIdFromPoint(x, y);
             if (taskId != -1) {
                 return taskId;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index b7e37b2..25148d1 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -88,7 +88,7 @@
                     }
                     taskId = task.mTaskId;
                 } else {
-                    taskId = displayContent.taskIdFromPoint(x, y);
+                    taskId = displayContent.taskForTapOutside(x, y);
                 }
             }
             if (taskId >= 0) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index b096bf2..5410676 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -430,25 +430,14 @@
     public abstract boolean isUidFocused(int uid);
 
     /**
-     * Checks whether the specified IME client has IME focus or not.
+     * Checks whether the specified process has IME focus or not.
      *
      * @param uid UID of the process to be queried
      * @param pid PID of the process to be queried
-     * @param displayId Display ID reported from the client. Note that this method also verifies
-     *                  whether the specified process is allowed to access to this display or not
-     * @return {@code true} if the IME client specified with {@code uid}, {@code pid}, and
-     *         {@code displayId} has IME focus
+     * @return {@code true} if a process that is identified by {@code uid} and {@code pid} has IME
+     *         focus
      */
-    public abstract boolean isInputMethodClientFocus(int uid, int pid, int displayId);
-
-    /**
-     * Checks whether the given {@code uid} is allowed to use the given {@code displayId} or not.
-     *
-     * @param displayId Display ID to be checked
-     * @param uid UID to be checked.
-     * @return {@code true} if the given {@code uid} is allowed to use the given {@code displayId}
-     */
-    public abstract boolean isUidAllowedOnDisplay(int displayId, int uid);
+    public abstract boolean isInputMethodClientFocus(int uid, int pid);
 
     /**
      * Return the display Id for given window.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e153a1d..14ea040 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -45,8 +45,8 @@
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -1928,7 +1928,7 @@
                     mAccessibilityController.onSomeWindowResizedOrMovedLocked();
                 }
 
-                if ((flagChanges & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+                if ((flagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                     updateNonSystemOverlayWindowsVisibilityIfNeeded(
                             win, win.mWinAnimator.getShown());
                 }
@@ -7201,20 +7201,16 @@
         }
 
         @Override
-        public boolean isInputMethodClientFocus(int uid, int pid, int displayId) {
-            if (displayId == Display.INVALID_DISPLAY) {
-                return false;
-            }
+        public boolean isInputMethodClientFocus(int uid, int pid) {
             synchronized (mWindowMap) {
-                final DisplayContent displayContent = mRoot.getTopFocusedDisplayContent();
-                if (displayContent == null
-                        || displayContent.getDisplayId() != displayId
-                        || !displayContent.hasAccess(uid)) {
-                    return false;
+                // Check all displays if any input method window has focus.
+                for (int i = mRoot.mChildren.size() - 1; i >= 0; --i) {
+                    final DisplayContent displayContent = mRoot.mChildren.get(i);
+                    if (displayContent.isInputMethodClientFocus(uid, pid)) {
+                        return true;
+                    }
                 }
-                if (displayContent.isInputMethodClientFocus(uid, pid)) {
-                    return true;
-                }
+
                 // Okay, how about this...  what is the current focus?
                 // It seems in some cases we may not have moved the IM
                 // target window, such as when it was in a pop-up window,
@@ -7223,7 +7219,7 @@
                 // press home.  Sometimes the IME won't go down.)
                 // Would be nice to fix this more correctly, but it's
                 // way at the end of a release, and this should be good enough.
-                final WindowState currentFocus = displayContent.mCurrentFocus;
+                final WindowState currentFocus = mRoot.getTopFocusedDisplayContent().mCurrentFocus;
                 if (currentFocus != null && currentFocus.mSession.mUid == uid
                         && currentFocus.mSession.mPid == pid) {
                     return true;
@@ -7233,20 +7229,6 @@
         }
 
         @Override
-        public boolean isUidAllowedOnDisplay(int displayId, int uid) {
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                return true;
-            }
-            if (displayId == Display.INVALID_DISPLAY) {
-                return false;
-            }
-            synchronized (mWindowMap) {
-                final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-                return displayContent != null && displayContent.hasAccess(uid);
-            }
-        }
-
-        @Override
         public int getDisplayIdForWindow(IBinder windowToken) {
             synchronized (mWindowMap) {
                 final WindowState window = mWindowMap.get(windowToken);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8276952..eacbda1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -46,12 +46,12 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -3470,7 +3470,7 @@
      * this window is visible.
      */
     boolean hideNonSystemOverlayWindowsWhenVisible() {
-        return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
+        return (mAttrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
                 && mSession.mCanHideNonSystemOverlayWindows;
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 52b849f..bbc4f44 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -468,6 +468,12 @@
             }
         }
 
+        // Diagnostic to ensure that the system is in a base healthy state. Done here as a common
+        // non-zygote process.
+        if (!VMRuntime.hasBootImageSpaces()) {
+            Slog.wtf(TAG, "Runtime is not running with a boot image!");
+        }
+
         // Loop forever.
         Looper.loop();
         throw new RuntimeException("Main thread loop unexpectedly exited");
diff --git a/services/net/java/android/net/ip/IpNeighborMonitor.java b/services/net/java/android/net/ip/IpNeighborMonitor.java
index fc07aa1..9512f1b 100644
--- a/services/net/java/android/net/ip/IpNeighborMonitor.java
+++ b/services/net/java/android/net/ip/IpNeighborMonitor.java
@@ -40,7 +40,6 @@
 import com.android.internal.util.BitUtils;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 import java.io.FileDescriptor;
 import java.net.InetAddress;
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 9d686ef..d197d01 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -28,7 +28,6 @@
 import android.net.util.InterfaceParams;
 import android.system.ErrnoException;
 import android.system.Os;
-import android.system.StructGroupReq;
 import android.system.StructTimeval;
 import android.util.Log;
 
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index cfcba3a..40098c1 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -32,7 +32,6 @@
 import android.system.StructTimeval;
 import android.util.Log;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 import java.io.FileDescriptor;
 import java.io.InterruptedIOException;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index fb57d68..7a847f3 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -726,6 +726,39 @@
     }
 
     @Test
+    public void testRunTask_whenSecondAgentUnavailable_commitsFirstAgentState() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        AgentMock agentMock = setUpAgent(PACKAGE_1);
+        setUpAgent(PACKAGE_2.unavailable());
+        agentOnBackupDo(
+                agentMock,
+                (oldState, dataOutput, newState) -> {
+                    writeData(dataOutput, "key", "data".getBytes());
+                    writeState(newState, "newState".getBytes());
+                });
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1, PACKAGE_2);
+
+        runTask(task);
+
+        assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1))).isEqualTo(
+                "newState".getBytes());
+    }
+
+    @Test
+    public void testRunTask_whenNonIncrementalAndAgentUnavailable() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1.unavailable());
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+        assertBackupPendingFor(PACKAGE_1);
+    }
+
+    @Test
     public void testRunTask_whenBindToAgentThrowsSecurityException() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         setUpAgent(PACKAGE_1);
@@ -743,6 +776,23 @@
     }
 
     @Test
+    public void testRunTask_whenNonIncrementalAndBindToAgentThrowsSecurityException() throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        setUpAgent(PACKAGE_1);
+        doThrow(SecurityException.class)
+                .when(mBackupManagerService)
+                .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+        runTask(task);
+
+        verify(mBackupManagerService).setWorkSource(null);
+        verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE);
+        verify(mObserver).backupFinished(BackupManager.SUCCESS);
+        assertBackupPendingFor(PACKAGE_1);
+    }
+
+    @Test
     public void testRunTask_whenTransportGetBackupQuotaThrows_notifiesCorrectly() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(transportMock.transport.getBackupQuota(PACKAGE_1.packageName, false))
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
deleted file mode 100644
index 9de64f2..0000000
--- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for exercising resizing bounds due to activity options.
- *
- * Build/Install/Run:
- *  atest FrameworksServicesTests:ActivityLaunchParamsModifierTests
- */
-@MediumTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class ActivityLaunchParamsModifierTests extends ActivityTestsBase {
-    private ActivityLaunchParamsModifier mModifier;
-    private ActivityTaskManagerService mService;
-    private ActivityStack mStack;
-    private TaskRecord mTask;
-    private ActivityRecord mActivity;
-
-    private LaunchParams mCurrent;
-    private LaunchParams mResult;
-
-    @Before
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        mService = createActivityTaskManagerService();
-        mModifier = new ActivityLaunchParamsModifier(mService.mStackSupervisor);
-        mCurrent = new LaunchParams();
-        mResult = new LaunchParams();
-
-
-        mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
-        mActivity = new ActivityBuilder(mService).setTask(mTask).build();
-    }
-
-
-    @Test
-    public void testSkippedInvocations() throws Exception {
-        // No specified activity should be ignored
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                null /*activity*/, null /*source*/, null /*options*/, mCurrent, mResult));
-
-        // No specified activity options should be ignored
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, null /*options*/, mCurrent, mResult));
-
-        // launch bounds specified should be ignored.
-        final ActivityOptions options = ActivityOptions.makeBasic();
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
-        // Non-resizeable records should be ignored
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-        assertFalse(mActivity.isResizeable());
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
-        // make record resizeable
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
-        assertTrue(mActivity.isResizeable());
-
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
-        // Does not support freeform
-        mService.mSupportsFreeformWindowManagement = false;
-        assertFalse(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
-        mService.mSupportsFreeformWindowManagement = true;
-        options.setLaunchBounds(new Rect());
-        assertTrue(mService.mStackSupervisor.canUseActivityOptionsLaunchBounds(options));
-
-        // Invalid bounds
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-        options.setLaunchBounds(new Rect(0, 0, -1, -1));
-        assertEquals(RESULT_SKIP, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-
-        // Valid bounds should cause the positioner to be applied.
-        options.setLaunchBounds(new Rect(0, 0, 100, 100));
-        assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-    }
-
-    @Test
-    public void testBoundsExtraction() throws Exception {
-        // Make activity resizeable and enable freeform mode.
-        mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
-        mService.mSupportsFreeformWindowManagement = true;
-
-        ActivityOptions options = ActivityOptions.makeBasic();
-        final Rect proposedBounds = new Rect(20, 30, 45, 40);
-        options.setLaunchBounds(proposedBounds);
-
-        assertEquals(RESULT_DONE, mModifier.onCalculate(null /*task*/, null /*layout*/,
-                mActivity, null /*source*/, options /*options*/, mCurrent, mResult));
-        assertEquals(mResult.mBounds, proposedBounds);
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
index 86541b9..65e4fa0 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -35,6 +35,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -165,17 +166,20 @@
     public void testSuspendedPackage() {
         mAInfo.applicationInfo.flags = FLAG_SUSPENDED;
         final String suspendingPackage = "com.test.suspending.package";
-        final String dialogMessage = "Test Message";
+        final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
+                .setMessage("Test Message")
+                .setIcon(0x11110001)
+                .build();
         when(mPackageManagerInternal.getSuspendingPackage(TEST_PACKAGE_NAME, TEST_USER_ID))
                 .thenReturn(suspendingPackage);
-        when(mPackageManagerInternal.getSuspendedDialogMessage(TEST_PACKAGE_NAME, TEST_USER_ID))
-                .thenReturn(dialogMessage);
+        when(mPackageManagerInternal.getSuspendedDialogInfo(TEST_PACKAGE_NAME, TEST_USER_ID))
+                .thenReturn(dialogInfo);
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
 
         // Check intent parameters
-        assertEquals(dialogMessage,
-                mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_DIALOG_MESSAGE));
+        assertEquals(dialogInfo,
+                mInterceptor.mIntent.getParcelableExtra(SuspendedAppActivity.EXTRA_DIALOG_INFO));
         assertEquals(suspendingPackage,
                 mInterceptor.mIntent.getStringExtra(SuspendedAppActivity.EXTRA_SUSPENDING_PACKAGE));
         assertEquals(TEST_PACKAGE_NAME,
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index f5b8f78..0d1302f 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -11,239 +11,1098 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.server.am;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
-import android.content.pm.ActivityInfo.WindowLayout;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 import android.view.Gravity;
 
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.am.LaunchParamsController.LaunchParams;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.Locale;
+
 /**
- * Tests for exercising resizing task bounds.
+ * Tests for default task bounds.
  *
  * Build/Install/Run:
  *  atest FrameworksServicesTests:TaskLaunchParamsModifierTests
  */
-@MediumTest
+@SmallTest
 @Presubmit
 @RunWith(AndroidJUnit4.class)
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
 public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
-    private final static int STACK_WIDTH = 100;
-    private final static int STACK_HEIGHT = 200;
 
-    private final static Rect STACK_BOUNDS = new Rect(0, 0, STACK_WIDTH, STACK_HEIGHT);
+    private ActivityRecord mActivity;
 
-    private ActivityTaskManagerService mService;
-    private ActivityStack mStack;
-    private TaskRecord mTask;
+    private TaskLaunchParamsModifier mTarget;
 
-    private TaskLaunchParamsModifier mPositioner;
-
-    private LaunchParamsController.LaunchParams mCurrent;
-    private LaunchParamsController.LaunchParams mResult;
+    private LaunchParams mCurrent;
+    private LaunchParams mResult;
 
     @Before
     @Override
     public void setUp() throws Exception {
         super.setUp();
 
-        mService = createActivityTaskManagerService();
-        mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        mStack.requestResize(STACK_BOUNDS);
+        setupActivityTaskManagerService();
+        mService.mSupportsFreeformWindowManagement = true;
+        when(mSupervisor.canUseActivityOptionsLaunchBounds(any())).thenCallRealMethod();
 
-        // We must create the task after resizing to make sure it does not inherit the stack
-        // dimensions on resize.
-        mTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+        mActivity = new ActivityBuilder(mService).build();
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        mActivity.info.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
 
-        mPositioner = new TaskLaunchParamsModifier();
+        mTarget = new TaskLaunchParamsModifier(mSupervisor);
 
-        mResult = new LaunchParamsController.LaunchParams();
-        mCurrent = new LaunchParamsController.LaunchParams();
+        mCurrent = new LaunchParams();
+        mCurrent.reset();
+        mResult = new LaunchParams();
+        mResult.reset();
     }
 
-    /**
-     * Ensures that the setup bounds are set as expected with the stack bounds set and the task
-     * bounds still {@code null}.
-     * @throws Exception
-     */
+    // =============================
+    // Display ID Related Tests
+    // =============================
     @Test
-    public void testInitialBounds() throws Exception {
-        assertEquals(mStack.getOverrideBounds(), STACK_BOUNDS);
-        assertEquals(mTask.getOverrideBounds(), new Rect());
+    public void testDefaultToPrimaryDisplay() {
+        createNewActivityDisplay(WINDOWING_MODE_FREEFORM);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(DEFAULT_DISPLAY, mResult.mPreferredDisplayId);
     }
 
-    /**
-     * Ensures that a task positioned with no {@link WindowLayout} receives the default launch
-     * position.
-     * @throws Exception
-     */
     @Test
-    public void testLaunchNoWindowLayout() throws Exception {
-        assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask, null /*layout*/,
-                null /*record*/, null /*source*/, null /*options*/, mCurrent, mResult));
-        assertEquals(getDefaultBounds(Gravity.NO_GRAVITY), mResult.mBounds);
+    public void testUsesPreviousDisplayIdIfSet() {
+        createNewActivityDisplay(WINDOWING_MODE_FREEFORM);
+        final TestActivityDisplay display = createNewActivityDisplay(WINDOWING_MODE_FULLSCREEN);
+
+        mCurrent.mPreferredDisplayId = display.mDisplayId;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(display.mDisplayId, mResult.mPreferredDisplayId);
     }
 
-    /**
-     * Ensures that a task positioned with an empty {@link WindowLayout} receives the default launch
-     * position.
-     * @throws Exception
-     */
     @Test
-    public void testlaunchEmptyWindowLayout() throws Exception {
-        assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
-                new WindowLayout(0, 0, 0, 0, Gravity.NO_GRAVITY, 0, 0), null /*activity*/,
-                null /*source*/, null /*options*/, mCurrent, mResult));
-        assertEquals(mResult.mBounds, getDefaultBounds(Gravity.NO_GRAVITY));
+    public void testUsesSourcesDisplayIdIfSet() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+        final TestActivityDisplay fullscreenDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FULLSCREEN);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        ActivityRecord source = createSourceActivity(fullscreenDisplay);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, /* options */ null, mCurrent, mResult));
+
+        assertEquals(fullscreenDisplay.mDisplayId, mResult.mPreferredDisplayId);
     }
 
-    /**
-     * Ensures that a task positioned with a {@link WindowLayout} gravity specified is positioned
-     * according to specification.
-     * @throws Exception
-     */
     @Test
-    public void testlaunchWindowLayoutGravity() throws Exception {
-        // Unspecified gravity should be ignored
-        testGravity(Gravity.NO_GRAVITY);
+    public void testUsesOptionsDisplayIdIfSet() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+        final TestActivityDisplay fullscreenDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FULLSCREEN);
 
-        // Unsupported gravity should be ignored
-        testGravity(Gravity.LEFT);
-        testGravity(Gravity.RIGHT);
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        ActivityRecord source = createSourceActivity(freeformDisplay);
 
-        // Test defaults for vertical gravities
-        testGravity(Gravity.TOP);
-        testGravity(Gravity.BOTTOM);
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
 
-        // Test corners
-        testGravity(Gravity.TOP | Gravity.LEFT);
-        testGravity(Gravity.TOP | Gravity.RIGHT);
-        testGravity(Gravity.BOTTOM | Gravity.LEFT);
-        testGravity(Gravity.BOTTOM | Gravity.RIGHT);
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, options, mCurrent, mResult));
+
+        assertEquals(fullscreenDisplay.mDisplayId, mResult.mPreferredDisplayId);
     }
 
-    private void testGravity(int gravity) {
-        try {
-            assertEquals(RESULT_CONTINUE, mPositioner.onCalculate(mTask,
-                    new WindowLayout(0, 0, 0, 0, gravity, 0, 0), null /*activity*/,
-                    null /*source*/, null /*options*/, mCurrent, mResult));
-            assertEquals(mResult.mBounds, getDefaultBounds(gravity));
-        } finally {
-            mCurrent.reset();
-            mResult.reset();
+    // =====================================
+    // Launch Windowing Mode Related Tests
+    // =====================================
+    @Test
+    public void testBoundsInOptionsInfersFreeformOnFreeformDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchBounds(new Rect(0, 0, 100, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testBoundsInOptionsInfersFreeformWithResizeableActivity() {
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchBounds(new Rect(0, 0, 100, 100));
+
+        mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testKeepsPictureInPictureLaunchModeInOptions() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testKeepsPictureInPictureLaunchModeWithBoundsInOptions() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+        options.setLaunchBounds(new Rect(0, 0, 100, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testKeepsFullscreenLaunchModeInOptionsOnNonFreeformDisplay() {
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testNonEmptyLayoutInfersFreeformOnFreeformDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testNonEmptyLayoutInfersFreeformWithEmptySize() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.LEFT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testNonEmptyLayoutInfersFreeformWithResizeableActivity() {
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).build();
+
+        mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testRespectsFullyResolvedCurrentParam_Fullscreen() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testRespectsModeFromFullyResolvedCurrentParam_NonEmptyBounds() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testForceMaximizesPreDApp() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+        options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.CUPCAKE;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testForceMaximizesAppWithoutMultipleDensitySupport() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+        options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        mActivity.appInfo.flags = 0;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testForceMaximizesUnresizeableApp() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+        options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testSkipsForceMaximizingAppsOnNonFreeformDisplay() {
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
+        options.setLaunchBounds(new Rect(0, 0, 200, 100));
+
+        mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testUsesFullscreenOnNonFreeformDisplay() {
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(DEFAULT_DISPLAY);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    @Test
+    public void testUsesFreeformByDefaultForPostNApp() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testUsesFreeformByDefaultForPreNResizeableAppWithoutOrientationRequest() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+                WINDOWING_MODE_FREEFORM);
+    }
+
+    @Test
+    public void testSkipsFreeformForPreNResizeableAppOnNonFullscreenDisplay() {
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(DEFAULT_DISPLAY);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
+                WINDOWING_MODE_FULLSCREEN);
+    }
+
+    // ================================
+    // Launching Bounds Related Tests
+    // ===============================
+    @Test
+    public void testKeepsBoundsWithPictureInPictureLaunchModeInOptions() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchWindowingMode(WINDOWING_MODE_PINNED);
+
+        final Rect expected = new Rect(0, 0, 100, 100);
+        options.setLaunchBounds(expected);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(expected, mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_LeftGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.LEFT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(0, mResult.mBounds.left);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.TOP).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(0, mResult.mBounds.top);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopLeftGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.TOP | Gravity.LEFT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(0, mResult.mBounds.left);
+        assertEquals(0, mResult.mBounds.top);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_RightGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.RIGHT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(1920, mResult.mBounds.right);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.BOTTOM).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(1080, mResult.mBounds.bottom);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomRightGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(1920, mResult.mBounds.right);
+        assertEquals(1080, mResult.mBounds.bottom);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_CenterToDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(900, 500, 1020, 580), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_LeftGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.LEFT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 500, 120, 580), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_TopGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.TOP).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(900, 0, 1020, 80), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_TopLeftGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.TOP | Gravity.LEFT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 0, 120, 80), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_RightGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.RIGHT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(1800, 500, 1920, 580), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_BottomGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(900, 1000, 1020, 1080), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsOnFreeformDisplay_RightBottomGravity() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(1800, 1000, 1920, 1080), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutFractionBoundsOnFreeformDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidthFraction(0.0625f).setHeightFraction(0.1f).build();
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(900, 486, 1020, 594), mResult.mBounds);
+    }
+
+    @Test
+    public void testNonEmptyLayoutBoundsWithResizeableActivity() {
+        final ActivityDisplay display = mSupervisor.getActivityDisplay(DEFAULT_DISPLAY);
+        display.setBounds(new Rect(0, 0, 1920, 1080));
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setWidth(120).setHeight(80).build();
+
+        mCurrent.mPreferredDisplayId = DEFAULT_DISPLAY;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(900, 500, 1020, 580), mResult.mBounds);
+    }
+
+    @Test
+    public void testRespectBoundsFromFullyResolvedCurrentParam_NonEmptyBounds() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
+    }
+
+    @Test
+    public void testDefaultSizeSmallerThanBigScreen() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        final int resultWidth = mResult.mBounds.width();
+        final int displayWidth = freeformDisplay.getBounds().width();
+        assertTrue("Result width " + resultWidth + " is not smaller than " + displayWidth,
+                resultWidth < displayWidth);
+
+        final int resultHeight = mResult.mBounds.height();
+        final int displayHeight = freeformDisplay.getBounds().height();
+        assertTrue("Result width " + resultHeight + " is not smaller than "
+                        + displayHeight, resultHeight < displayHeight);
+    }
+
+    @Test
+    public void testDefaultFreeformSizeCenteredToDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        final Rect displayBounds = freeformDisplay.getBounds();
+        assertEquals("Distance to left and right should be equal.",
+                mResult.mBounds.left - displayBounds.left,
+                displayBounds.right - mResult.mBounds.right);
+        assertEquals("Distance to top and bottom should be equal.",
+                mResult.mBounds.top - displayBounds.top,
+                displayBounds.bottom - mResult.mBounds.bottom);
+    }
+
+    @Test
+    public void testCascadesToSourceSizeForFreeform() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        final ActivityRecord source = createSourceActivity(freeformDisplay);
+        source.setBounds(0, 0, 412, 732);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, options, mCurrent, mResult));
+
+        final Rect displayBounds = freeformDisplay.getBounds();
+        assertTrue("Left bounds should be larger than 0.", mResult.mBounds.left > 0);
+        assertTrue("Top bounds should be larger than 0.", mResult.mBounds.top > 0);
+        assertTrue("Bounds should be centered at somewhere in the left half, but it's "
+                + "centerX is " + mResult.mBounds.centerX(),
+                mResult.mBounds.centerX() < displayBounds.centerX());
+        assertTrue("Bounds should be centered at somewhere in the top half, but it's "
+                        + "centerY is " + mResult.mBounds.centerY(),
+                mResult.mBounds.centerY() < displayBounds.centerY());
+    }
+
+    @Test
+    public void testAdjustBoundsToFitDisplay_TopLeftOutOfDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        final ActivityRecord source = createSourceActivity(freeformDisplay);
+        source.setBounds(0, 0, 200, 400);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, options, mCurrent, mResult));
+
+        final Rect displayBounds = freeformDisplay.getBounds();
+        assertTrue("display bounds doesn't contain result. display bounds: "
+                + displayBounds + " result: " + mResult.mBounds,
+                displayBounds.contains(mResult.mBounds));
+    }
+
+    @Test
+    public void testAdjustBoundsToFitDisplay_BottomRightOutOfDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        final ActivityRecord source = createSourceActivity(freeformDisplay);
+        source.setBounds(1720, 680, 1920, 1080);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, options, mCurrent, mResult));
+
+        final Rect displayBounds = freeformDisplay.getBounds();
+        assertTrue("display bounds doesn't contain result. display bounds: "
+                        + displayBounds + " result: " + mResult.mBounds,
+                displayBounds.contains(mResult.mBounds));
+    }
+
+    @Test
+    public void testAdjustBoundsToFitDisplay_LargerThanDisplay() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.setTo(mSupervisor.getOverrideConfiguration());
+        overrideConfig.setLayoutDirection(new Locale("ar"));
+        mSupervisor.onConfigurationChanged(overrideConfig);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        final ActivityRecord source = createSourceActivity(freeformDisplay);
+        source.setBounds(1720, 680, 1920, 1080);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, source, options, mCurrent, mResult));
+
+        final Rect displayBounds = freeformDisplay.getBounds();
+        assertTrue("display bounds doesn't contain result. display bounds: "
+                        + displayBounds + " result: " + mResult.mBounds,
+                displayBounds.contains(mResult.mBounds));
+    }
+
+    @Test
+    public void testRespectsLayoutMinDimensions() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
+                .setMinWidth(500).setMinHeight(800).build();
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
+                /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(500, mResult.mBounds.width());
+        assertEquals(800, mResult.mBounds.height());
+    }
+
+    @Test
+    public void testRotatesInPlaceInitialBoundsMismatchOrientation() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(100, 100, 500, 300));
+
+        mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(200, 0, 400, 400), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToRightForCloseToLeftBoundsWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(50, 50, 100, 150));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(50, 50, 500, 300));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(170, 50, 620, 300), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToLeftForCloseToRightBoundsWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(1720, 50, 1830, 150));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(1720, 50, 1850, 300));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(1600, 50, 1730, 300), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToRightFirstForHorizontallyCenteredAndCloseToTopWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(0, 0, 100, 300));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(0, 0, 1800, 200));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(120, 0, 1920, 200), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToLeftNoSpaceOnRightForHorizontallyCenteredAndCloseToTopWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(120, 0, 240, 300));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(120, 0, 1860, 200));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 0, 1740, 200), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToBottomRightFirstForCenteredBoundsWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(120, 0, 240, 100));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(120, 0, 1800, 1013));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(240, 67, 1920, 1080), mResult.mBounds);
+    }
+
+    @Test
+    public void testShiftsToTopLeftIfNoSpaceOnBottomRightForCenteredBoundsWhenConflict() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(120, 67, 240, 100));
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+        options.setLaunchBounds(new Rect(120, 67, 1800, 1020));
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 0, 1680,
+                953), mResult.mBounds);
+    }
+
+    private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
+        final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
+        display.setWindowingMode(windowingMode);
+        display.setBounds(/* left */ 0, /* top */ 0, /* right */ 1920, /* bottom */ 1080);
+        display.getConfiguration().densityDpi = DENSITY_DEFAULT;
+        return display;
+    }
+
+    private ActivityRecord createSourceActivity(TestActivityDisplay display) {
+        final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+                ACTIVITY_TYPE_STANDARD, true);
+        return new ActivityBuilder(mService).setStack(stack).setCreateTask(true).build();
+    }
+
+    private void addFreeformTaskTo(TestActivityDisplay display, Rect bounds) {
+        final TestActivityStack stack = display.createStack(display.getWindowingMode(),
+                ACTIVITY_TYPE_STANDARD, true);
+        stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+        task.setBounds(bounds);
+    }
+
+    private void assertEquivalentWindowingMode(int expected, int actual, int parentWindowingMode) {
+        if (expected != parentWindowingMode) {
+            assertEquals(expected, actual);
+        } else {
+            assertEquals(WINDOWING_MODE_UNDEFINED, actual);
         }
     }
 
-    /**
-     * Ensures that a task which causes a conflict with another task when positioned is adjusted as
-     * expected.
-     * @throws Exception
-     */
-    @Test
-    public void testLaunchWindowCenterConflict() throws Exception {
-        testConflict(Gravity.NO_GRAVITY);
-        testConflict(Gravity.TOP);
-        testConflict(Gravity.BOTTOM);
-        testConflict(Gravity.TOP | Gravity.LEFT);
-        testConflict(Gravity.TOP | Gravity.RIGHT);
-        testConflict(Gravity.BOTTOM | Gravity.LEFT);
-        testConflict(Gravity.BOTTOM | Gravity.RIGHT);
-    }
+    private static class WindowLayoutBuilder {
+        private int mWidth = -1;
+        private int mHeight = -1;
+        private float mWidthFraction = -1f;
+        private float mHeightFraction = -1f;
+        private int mGravity = Gravity.NO_GRAVITY;
+        private int mMinWidth = -1;
+        private int mMinHeight = -1;
 
-    private void testConflict(int gravity) {
-        final WindowLayout layout = new WindowLayout(0, 0, 0, 0, gravity, 0, 0);
-
-        // layout first task
-        mService.mStackSupervisor.getLaunchParamsController().layoutTask(mTask, layout);
-
-        // Second task will be laid out on top of the first so starting bounds is the same.
-        final Rect expectedBounds = new Rect(mTask.getOverrideBounds());
-
-        ActivityRecord activity = null;
-        TaskRecord secondTask = null;
-
-        // wrap with try/finally to ensure cleanup of activity/stack.
-        try {
-            // empty tasks are ignored in conflicts
-            activity = new ActivityBuilder(mService).setTask(mTask).build();
-
-            // Create secondary task
-            secondTask = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
-
-            // layout second task
-            assertEquals(RESULT_CONTINUE,
-                    mPositioner.onCalculate(secondTask, layout, null /*activity*/,
-                            null /*source*/, null /*options*/, mCurrent, mResult));
-
-            if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)
-                    || (gravity & (Gravity.BOTTOM | Gravity.RIGHT))
-                    == (Gravity.BOTTOM | Gravity.RIGHT)) {
-                expectedBounds.offset(-TaskLaunchParamsModifier.getHorizontalStep(
-                        mStack.getOverrideBounds()), 0);
-            } else if ((gravity & Gravity.TOP) == Gravity.TOP
-                    || (gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
-                expectedBounds.offset(
-                        TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()), 0);
-            } else {
-                expectedBounds.offset(
-                        TaskLaunchParamsModifier.getHorizontalStep(mStack.getOverrideBounds()),
-                        TaskLaunchParamsModifier.getVerticalStep(mStack.getOverrideBounds()));
-            }
-
-            assertEquals(mResult.mBounds, expectedBounds);
-        } finally {
-            // Remove task and activity to prevent influencing future tests
-            if (activity != null) {
-                mTask.removeActivity(activity);
-            }
-
-            if (secondTask != null) {
-                mStack.removeTask(secondTask, "cleanup", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
-            }
-        }
-    }
-
-    private Rect getDefaultBounds(int gravity) {
-        final Rect bounds = new Rect();
-        bounds.set(mStack.getOverrideBounds());
-
-        final int verticalInset =
-                TaskLaunchParamsModifier.getFreeformStartTop(mStack.getOverrideBounds());
-        final int horizontalInset =
-                TaskLaunchParamsModifier.getFreeformStartLeft(mStack.getOverrideBounds());
-
-        bounds.inset(horizontalInset, verticalInset);
-
-        if ((gravity & (Gravity.TOP | Gravity.RIGHT)) == (Gravity.TOP | Gravity.RIGHT)) {
-            bounds.offsetTo(horizontalInset * 2, 0);
-        } else if ((gravity & Gravity.TOP) == Gravity.TOP) {
-            bounds.offsetTo(0, 0);
-        } else if ((gravity & (Gravity.BOTTOM | Gravity.RIGHT))
-                == (Gravity.BOTTOM | Gravity.RIGHT)) {
-            bounds.offsetTo(horizontalInset * 2, verticalInset * 2);
-        } else if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) {
-            bounds.offsetTo(0, verticalInset * 2);
+        private WindowLayoutBuilder setWidth(int width) {
+            mWidth = width;
+            return this;
         }
 
-        return bounds;
+        private WindowLayoutBuilder setHeight(int height) {
+            mHeight = height;
+            return this;
+        }
+
+        private WindowLayoutBuilder setWidthFraction(float widthFraction) {
+            mWidthFraction = widthFraction;
+            return this;
+        }
+
+        private WindowLayoutBuilder setHeightFraction(float heightFraction) {
+            mHeightFraction = heightFraction;
+            return this;
+        }
+
+        private WindowLayoutBuilder setGravity(int gravity) {
+            mGravity = gravity;
+            return this;
+        }
+
+        private WindowLayoutBuilder setMinWidth(int minWidth) {
+            mMinWidth = minWidth;
+            return this;
+        }
+
+        private WindowLayoutBuilder setMinHeight(int minHeight) {
+            mMinHeight = minHeight;
+            return this;
+        }
+
+        private ActivityInfo.WindowLayout build() {
+            return new ActivityInfo.WindowLayout(mWidth, mWidthFraction, mHeight, mHeightFraction,
+                    mGravity, mMinWidth, mMinHeight);
+        }
     }
 }
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 c3c0788..517b5ad 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -37,6 +37,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
+import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.os.BaseBundle;
 import android.os.PersistableBundle;
@@ -200,13 +201,21 @@
                 PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
         final PersistableBundle launcherExtras1 = getPersistableBundle(
                 PACKAGE_NAME_1, 10L, 0.1, false, "launcherString1");
-        ps1.setSuspended(true, "suspendingPackage1", "dialogMsg1", appExtras1, launcherExtras1, 0);
+
+        final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
+                .setIcon(0x11220001)
+                .setTitle(0x11220002)
+                .setMessage("1st message")
+                .setNeutralButtonText(0x11220003)
+                .build();
+
+        ps1.setSuspended(true, "suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1, 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
 
-        ps2.setSuspended(true, "suspendingPackage2", "dialogMsg2", null, null, 0);
+        ps2.setSuspended(true, "suspendingPackage2", null, null, null, 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
 
-        ps3.setSuspended(false, "irrelevant", "irrevelant2", null, null, 0);
+        ps3.setSuspended(false, "irrelevant", dialogInfo1, null, null, 0);
         settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
 
         settingsUnderTest.writePackageRestrictionsLPr(0);
@@ -221,7 +230,7 @@
                 readUserState(0);
         assertThat(readPus1.suspended, is(true));
         assertThat(readPus1.suspendingPackage, equalTo("suspendingPackage1"));
-        assertThat(readPus1.dialogMessage, equalTo("dialogMsg1"));
+        assertThat(readPus1.dialogInfo, equalTo(dialogInfo1));
         assertThat(BaseBundle.kindofEquals(readPus1.suspendedAppExtras, appExtras1), is(true));
         assertThat(BaseBundle.kindofEquals(readPus1.suspendedLauncherExtras, launcherExtras1),
                 is(true));
@@ -230,7 +239,7 @@
                 readUserState(0);
         assertThat(readPus2.suspended, is(true));
         assertThat(readPus2.suspendingPackage, equalTo("suspendingPackage2"));
-        assertThat(readPus2.dialogMessage, equalTo("dialogMsg2"));
+        assertThat(readPus2.dialogInfo, is(nullValue()));
         assertThat(readPus2.suspendedAppExtras, is(nullValue()));
         assertThat(readPus2.suspendedLauncherExtras, is(nullValue()));
 
@@ -238,7 +247,7 @@
                 readUserState(0);
         assertThat(readPus3.suspended, is(false));
         assertThat(readPus3.suspendingPackage, is(nullValue()));
-        assertThat(readPus3.dialogMessage, is(nullValue()));
+        assertThat(readPus3.dialogInfo, is(nullValue()));
         assertThat(readPus3.suspendedAppExtras, is(nullValue()));
         assertThat(readPus3.suspendedLauncherExtras, is(nullValue()));
     }
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 4a33ca3..f0ed612 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertThat;
 
 import android.content.pm.PackageUserState;
+import android.content.pm.SuspendDialogInfo;
 import android.os.PersistableBundle;
 import android.util.ArraySet;
 
@@ -37,7 +38,7 @@
 public class PackageUserStateTest {
 
     @Test
-    public void testPackageUserState01()  {
+    public void testPackageUserState01() {
         final PackageUserState testUserState = new PackageUserState();
         PackageUserState oldUserState;
 
@@ -84,7 +85,7 @@
     }
 
     @Test
-    public void testPackageUserState02()  {
+    public void testPackageUserState02() {
         final PackageUserState testUserState01 = new PackageUserState();
         PackageUserState oldUserState;
 
@@ -102,7 +103,7 @@
     }
 
     @Test
-    public void testPackageUserState03()  {
+    public void testPackageUserState03() {
         final PackageUserState oldUserState = new PackageUserState();
 
         // only new user state has array defined; different
@@ -138,7 +139,7 @@
     }
 
     @Test
-    public void testPackageUserState04()  {
+    public void testPackageUserState04() {
         final PackageUserState oldUserState = new PackageUserState();
 
         // only new user state has array defined; different
@@ -185,15 +186,19 @@
         launcherExtras2.putString("name", "launcherExtras2");
         final String suspendingPackage1 = "package1";
         final String suspendingPackage2 = "package2";
-        final String dialogMessage1 = "dialogMessage1";
-        final String dialogMessage2 = "dialogMessage2";
+        final SuspendDialogInfo dialogInfo1 = new SuspendDialogInfo.Builder()
+                .setMessage("dialogMessage1")
+                .build();
+        final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
+                .setMessage("dialogMessage2")
+                .build();
 
         final PackageUserState testUserState1 = new PackageUserState();
         testUserState1.suspended = true;
         testUserState1.suspendedAppExtras = appExtras1;
         testUserState1.suspendedLauncherExtras = launcherExtras1;
         testUserState1.suspendingPackage = suspendingPackage1;
-        testUserState1.dialogMessage = dialogMessage1;
+        testUserState1.dialogInfo = dialogInfo1;
 
         PackageUserState testUserState2 = new PackageUserState(testUserState1);
         assertThat(testUserState1.equals(testUserState2), is(true));
@@ -209,14 +214,14 @@
         assertThat(testUserState1.equals(testUserState2), is(false));
 
         testUserState2 = new PackageUserState(testUserState1);
-        testUserState2.dialogMessage = dialogMessage2;
+        testUserState2.dialogInfo = dialogInfo2;
         assertThat(testUserState1.equals(testUserState2), is(false));
 
         testUserState2 = new PackageUserState(testUserState1);
         testUserState2.suspended = testUserState1.suspended = false;
         // Everything is different but irrelevant if suspended is false
         testUserState2.suspendingPackage = suspendingPackage2;
-        testUserState2.dialogMessage = dialogMessage2;
+        testUserState2.dialogInfo = dialogInfo2;
         testUserState2.suspendedAppExtras = appExtras2;
         testUserState2.suspendedLauncherExtras = launcherExtras2;
         assertThat(testUserState1.equals(testUserState2), is(true));
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
new file mode 100644
index 0000000..7eccd67
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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 com.android.server.pm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import android.content.pm.SuspendDialogInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SuspendDialogInfoTest {
+    private static final int VALID_TEST_RES_ID_1 = 0x11110001;
+    private static final int VALID_TEST_RES_ID_2 = 0x11110002;
+
+    private static SuspendDialogInfo.Builder createDefaultDialogBuilder() {
+        return new SuspendDialogInfo.Builder()
+                .setIcon(VALID_TEST_RES_ID_1)
+                .setTitle(VALID_TEST_RES_ID_1)
+                .setMessage(VALID_TEST_RES_ID_1)
+                .setNeutralButtonText(VALID_TEST_RES_ID_1);
+    }
+
+    @Test
+    public void equalsComparesIcons() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+        final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+        // Only icon is different
+        dialogBuilder2.setIcon(VALID_TEST_RES_ID_2);
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void equalsComparesTitle() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+        final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+        // Only title is different
+        dialogBuilder2.setTitle(VALID_TEST_RES_ID_2);
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void equalsComparesButtonText() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+        final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+        // Only button text is different
+        dialogBuilder2.setNeutralButtonText(VALID_TEST_RES_ID_2);
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void equalsComparesMessageIds() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+        final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+        // Only message is different
+        dialogBuilder2.setMessage(VALID_TEST_RES_ID_2);
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void equalsIgnoresMessageStringsWhenIdsSet() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = new SuspendDialogInfo.Builder()
+                .setMessage(VALID_TEST_RES_ID_1)
+                .setMessage("1st message");
+        final SuspendDialogInfo.Builder dialogBuilder2 = new SuspendDialogInfo.Builder()
+                .setMessage(VALID_TEST_RES_ID_1)
+                .setMessage("2nd message");
+        // String messages different but should get be ignored when resource ids are set
+        assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void equalsComparesMessageStringsWhenNoIdsSet() {
+        final SuspendDialogInfo.Builder dialogBuilder1 = new SuspendDialogInfo.Builder()
+                .setMessage("1st message");
+        final SuspendDialogInfo.Builder dialogBuilder2 = new SuspendDialogInfo.Builder()
+                .setMessage("2nd message");
+        // Both have different messages, which are not ignored as resource ids aren't set
+        assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+    }
+
+    @Test
+    public void messageStringClearedWhenResIdSet() {
+        final SuspendDialogInfo dialogInfo = new SuspendDialogInfo.Builder()
+                .setMessage(VALID_TEST_RES_ID_2)
+                .setMessage("Should be cleared on build")
+                .build();
+        assertNull(dialogInfo.getDialogMessage());
+        assertEquals(VALID_TEST_RES_ID_2, dialogInfo.getDialogMessageResId());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index f115b9c..553d234 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -33,6 +33,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
+import android.content.pm.SuspendDialogInfo;
 import android.content.res.Resources;
 import android.os.BaseBundle;
 import android.os.Bundle;
@@ -152,7 +153,7 @@
         }
 
         void drainPendingBroadcasts() {
-            while (pollForIntent(5) != null);
+            while (pollForIntent(5) != null) ;
         }
 
         Intent receiveIntentFromApp() {
@@ -215,15 +216,15 @@
     }
 
     private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
-            String dialogMessage) {
+            SuspendDialogInfo dialogInfo) {
         final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
-                PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogMessage);
+                PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogInfo);
         assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
     }
 
     private void unsuspendTestPackage() {
         final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
-                PACKAGES_TO_SUSPEND, false, null, null, null);
+                PACKAGES_TO_SUSPEND, false, null, null, (SuspendDialogInfo) null);
         assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
     }
 
@@ -318,7 +319,8 @@
     @Test
     public void testCannotSuspendSelf() {
         final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
-                new String[]{mContext.getOpPackageName()}, true, null, null, null);
+                new String[]{mContext.getOpPackageName()}, true, null, null,
+                (SuspendDialogInfo) null);
         assertTrue(unchangedPkgs.length == 1);
         assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
     }
@@ -457,7 +459,8 @@
         mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
                 ACTION_REPORT_TEST_ACTIVITY_STARTED);
         final String testMessage = "This is a test message to report suspension of %1$s";
-        suspendTestPackage(null, null, testMessage);
+        suspendTestPackage(null, null,
+                new SuspendDialogInfo.Builder().setMessage(testMessage).build());
         startTestAppActivity();
         assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
         assertNotNull("Given dialog message not shown", mUiDevice.wait(
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 6d31dfb..7935ec1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -33,10 +35,12 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.Surface;
 import android.view.WindowManager;
@@ -255,4 +259,30 @@
         closingWindow.removeIfPossible();
         assertTrue(closingWindow.mRemoved);
     }
+
+    @Test
+    public void testTransitionAnimationPositionAndBounds() {
+        final Rect stackBounds = new Rect(
+                0/* left */, 0 /* top */, 1000 /* right */, 1000 /* bottom */);
+        final Rect taskBounds = new Rect(
+                100/* left */, 200 /* top */, 600 /* right */, 600 /* bottom */);
+        mStack.setBounds(stackBounds);
+        mTask.setBounds(taskBounds);
+
+        mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertTransitionAnimationPositionAndBounds(taskBounds.left, taskBounds.top, stackBounds);
+
+        mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        assertTransitionAnimationPositionAndBounds(stackBounds.left, stackBounds.top, stackBounds);
+    }
+
+    private void assertTransitionAnimationPositionAndBounds(int expectedX, int expectedY,
+            Rect expectedBounds) {
+        final Point outPosition = new Point();
+        final Rect outBounds = new Rect();
+        mToken.getAnimationBounds(outPosition, outBounds);
+        assertEquals(expectedX, outPosition.x);
+        assertEquals(expectedY, outPosition.y);
+        assertEquals(expectedBounds, outBounds);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index 7125246..3c8b2a0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -40,27 +40,25 @@
 import android.view.SurfaceSession;
 import android.view.View;
 
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests for the {@link DragDropController} class.
  *
- * atest FrameworksServicesTests:com.android.server.wm.DragDropControllerTests
+ * Build/Install/Run:
+ *  atest FrameworksServicesTests:com.android.server.wm.DragDropControllerTests
  */
 @SmallTest
-@RunWith(AndroidJUnit4.class)
 @Presubmit
 public class DragDropControllerTests extends WindowTestsBase {
     private static final int TIMEOUT_MS = 3000;
@@ -109,6 +107,7 @@
         return window;
     }
 
+    @Override
     @Before
     public void setUp() throws Exception {
         final UserManagerInternal userManager = mock(UserManagerInternal.class);
@@ -127,6 +126,7 @@
         }
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         LocalServices.removeServiceForTest(UserManagerInternal.class);
@@ -139,25 +139,25 @@
                 mTarget.cancelDragAndDrop(mToken);
             }
             latch = new CountDownLatch(1);
-            mTarget.setOnClosedCallbackLocked(() -> {
-                latch.countDown();
-            });
+            mTarget.setOnClosedCallbackLocked(latch::countDown);
         }
         assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+        super.tearDown();
     }
 
     @Test
-    public void testDragFlow() throws Exception {
+    public void testDragFlow() {
         dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
     }
 
     @Test
-    public void testPerformDrag_NullDataWithGrantUri() throws Exception {
+    public void testPerformDrag_NullDataWithGrantUri() {
         dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
     }
 
     @Test
-    public void testPerformDrag_NullDataToOtherUser() throws Exception {
+    public void testPerformDrag_NullDataToOtherUser() {
         final WindowState otherUsersWindow =
                 createDropTargetWindow("Other user's window", 1 * UserHandle.PER_USER_RANGE);
         doReturn(otherUsersWindow).when(mDisplayContent).getTouchableWinAtPointLocked(10, 10);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 6f4f173..33b137e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -29,14 +29,14 @@
 import android.graphics.Rect;
 import android.os.UserManager;
 
-import androidx.test.InstrumentationRegistry;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
 
 import java.io.File;
 
+import androidx.test.InstrumentationRegistry;
+
 /**
  * Base class for tests that use a {@link TaskSnapshotPersister}.
  */
@@ -54,9 +54,11 @@
         sFilesDir = InstrumentationRegistry.getContext().getFilesDir();
     }
 
+    @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
         final UserManager um = UserManager.get(InstrumentationRegistry.getContext());
         mTestUserId = um.getUserHandle();
         mPersister = new TaskSnapshotPersister(userId -> sFilesDir);
@@ -64,9 +66,12 @@
         mPersister.start();
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         cleanDirectory();
+
+        super.tearDown();
     }
 
     private void cleanDirectory() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index ea44279..0e9a63c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -19,36 +19,37 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
 
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
+
+import androidx.test.filters.SmallTest;
 
 /**
  * Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
  *
  * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
+ *  atest FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
  */
 @SmallTest
 @Presubmit
-@RunWith(AndroidJUnit4.class)
 public class TaskStackContainersTests extends WindowTestsBase {
 
     private TaskStack mPinnedStack;
 
+    @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
         mPinnedStack = createStackControllerOnStackOnDisplay(
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         // Stack should contain visible app window to be considered visible.
@@ -60,13 +61,16 @@
         assertTrue(mPinnedStack.isVisible());
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         mPinnedStack.removeImmediately();
+
+        super.tearDown();
     }
 
     @Test
-    public void testStackPositionChildAt() throws Exception {
+    public void testStackPositionChildAt() {
         // Test that always-on-top stack can't be moved to position other than top.
         final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
         final TaskStack stack2 = createTaskStackOnDisplay(mDisplayContent);
@@ -76,8 +80,8 @@
         final int stack1Pos = taskStackContainer.mChildren.indexOf(stack1);
         final int stack2Pos = taskStackContainer.mChildren.indexOf(stack2);
         final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
-        assertGreaterThan(pinnedStackPos, stack2Pos);
-        assertGreaterThan(stack2Pos, stack1Pos);
+        assertThat(pinnedStackPos).isGreaterThan(stack2Pos);
+        assertThat(stack2Pos).isGreaterThan(stack1Pos);
 
         taskStackContainer.positionChildAt(WindowContainer.POSITION_BOTTOM, mPinnedStack, false);
         assertEquals(taskStackContainer.mChildren.get(stack1Pos), stack1);
@@ -91,7 +95,7 @@
     }
 
     @Test
-    public void testStackPositionBelowPinnedStack() throws Exception {
+    public void testStackPositionBelowPinnedStack() {
         // Test that no stack can be above pinned stack.
         final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
 
@@ -99,7 +103,7 @@
 
         final int stackPos = taskStackContainer.mChildren.indexOf(stack1);
         final int pinnedStackPos = taskStackContainer.mChildren.indexOf(mPinnedStack);
-        assertGreaterThan(pinnedStackPos, stackPos);
+        assertThat(pinnedStackPos).isGreaterThan(stackPos);
 
         taskStackContainer.positionChildAt(WindowContainer.POSITION_TOP, stack1, false);
         assertEquals(taskStackContainer.mChildren.get(stackPos), stack1);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 70e4ce4..cf67d78 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -48,18 +48,17 @@
 import android.view.IWindow;
 import android.view.WindowManager;
 
-import androidx.test.InstrumentationRegistry;
-
 import com.android.server.AttributeCache;
 
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 
 import java.util.HashSet;
 import java.util.LinkedList;
 
+import androidx.test.InstrumentationRegistry;
+
 /**
  * Common base class for window manager unit test classes.
  *
@@ -194,14 +193,6 @@
         }
     }
 
-    /**
-     * @return A SurfaceBuilderFactory to inject in to the WindowManagerService during
-     *         set-up (or null).
-     */
-    SurfaceBuilderFactory getSurfaceBuilderFactory() {
-        return null;
-    }
-
     private WindowState createCommonWindow(WindowState parent, int type, String name) {
         synchronized (sWm.mWindowMap) {
             final WindowState win = createWindow(parent, type, name);
@@ -212,16 +203,6 @@
         }
     }
 
-    /** Asserts that the first entry is greater than the second entry. */
-    void assertGreaterThan(int first, int second) throws Exception {
-        Assert.assertTrue("Excepted " + first + " to be greater than " + second, first > second);
-    }
-
-    /** Asserts that the first entry is greater than the second entry. */
-    void assertLessThan(int first, int second) throws Exception {
-        Assert.assertTrue("Excepted " + first + " to be less than " + second, first < second);
-    }
-
     /**
      * Waits until the main handler for WM has processed all messages.
      */
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 8f9fb1b..a610e6e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -32,36 +32,35 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
 import org.junit.After;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 
 import java.util.HashMap;
 import java.util.LinkedList;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests for the {@link WindowLayersController} class.
  *
  * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.ZOrderingTests
+ *  atest FrameworksServicesTests:com.android.server.wm.ZOrderingTests
  */
 @SmallTest
 @FlakyTest(bugId = 74078662)
 @Presubmit
-@RunWith(AndroidJUnit4.class)
 public class ZOrderingTests extends WindowTestsBase {
 
     private class LayerRecordingTransaction extends SurfaceControl.Transaction {
-        HashMap<SurfaceControl, Integer> mLayersForControl = new HashMap();
-        HashMap<SurfaceControl, SurfaceControl> mRelativeLayersForControl = new HashMap();
+        HashMap<SurfaceControl, Integer> mLayersForControl = new HashMap<>();
+        HashMap<SurfaceControl, SurfaceControl> mRelativeLayersForControl = new HashMap<>();
 
         @Override
         public SurfaceControl.Transaction setLayer(SurfaceControl sc, int layer) {
@@ -86,11 +85,11 @@
         private SurfaceControl getRelativeLayer(SurfaceControl sc) {
             return mRelativeLayersForControl.get(sc);
         }
-    };
+    }
 
     // We have WM use our Hierarchy recording subclass of SurfaceControl.Builder
     // such that we can keep track of the parents of Surfaces as they are constructed.
-    private HashMap<SurfaceControl, SurfaceControl> mParentFor = new HashMap();
+    private HashMap<SurfaceControl, SurfaceControl> mParentFor = new HashMap<>();
 
     private class HierarchyRecorder extends SurfaceControl.Builder {
         SurfaceControl mPendingParent;
@@ -109,13 +108,13 @@
             mPendingParent = null;
             return sc;
         }
-    };
+    }
 
     class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
         public SurfaceControl.Builder make(SurfaceSession s) {
             return new HierarchyRecorder(s);
         }
-    };
+    }
 
     private LayerRecordingTransaction mTransaction;
 
@@ -136,7 +135,7 @@
     }
 
     LinkedList<SurfaceControl> getAncestors(LayerRecordingTransaction t, SurfaceControl sc) {
-        LinkedList<SurfaceControl> p = new LinkedList();
+        LinkedList<SurfaceControl> p = new LinkedList<>();
         SurfaceControl current = sc;
         do {
             p.addLast(current);
@@ -153,7 +152,7 @@
 
 
     void assertZOrderGreaterThan(LayerRecordingTransaction t, SurfaceControl left,
-            SurfaceControl right) throws Exception {
+            SurfaceControl right) {
         final LinkedList<SurfaceControl> leftParentChain = getAncestors(t, left);
         final LinkedList<SurfaceControl> rightParentChain = getAncestors(t, right);
 
@@ -168,16 +167,15 @@
         }
 
         if (rightTop == null) { // right is the parent of left.
-            assertGreaterThan(t.getLayer(leftTop), 0);
+            assertThat(t.getLayer(leftTop)).isGreaterThan(0);
         } else if (leftTop == null) { // left is the parent of right.
-            assertGreaterThan(0, t.getLayer(rightTop));
+            assertThat(t.getLayer(rightTop)).isLessThan(0);
         } else {
-            assertGreaterThan(t.getLayer(leftTop),
-                    t.getLayer(rightTop));
+            assertThat(t.getLayer(leftTop)).isGreaterThan(t.getLayer(rightTop));
         }
     }
 
-    void assertWindowHigher(WindowState left, WindowState right) throws Exception {
+    void assertWindowHigher(WindowState left, WindowState right) {
         assertZOrderGreaterThan(mTransaction, left.getSurfaceControl(), right.getSurfaceControl());
     }
 
@@ -186,7 +184,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForImeWithNoTarget() throws Exception {
+    public void testAssignWindowLayers_ForImeWithNoTarget() {
         sWm.mInputMethodTarget = null;
         mDisplayContent.assignChildLayers(mTransaction);
 
@@ -203,7 +201,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForImeWithAppTarget() throws Exception {
+    public void testAssignWindowLayers_ForImeWithAppTarget() {
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         sWm.mInputMethodTarget = imeAppTarget;
 
@@ -222,7 +220,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
+    public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() {
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
                 TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
@@ -248,7 +246,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
+    public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() {
         final WindowState appBelowImeTarget = createWindow("appBelowImeTarget");
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
@@ -271,7 +269,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForImeNonAppImeTarget() throws Exception {
+    public void testAssignWindowLayers_ForImeNonAppImeTarget() {
         final WindowState imeSystemOverlayTarget = createWindow(null, TYPE_SYSTEM_OVERLAY,
                 mDisplayContent, "imeSystemOverlayTarget",
                 true /* ownerCanAddInternalSystemWindow */);
@@ -298,7 +296,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForStatusBarImeTarget() throws Exception {
+    public void testAssignWindowLayers_ForStatusBarImeTarget() {
         sWm.mInputMethodTarget = mStatusBarWindow;
         mDisplayContent.assignChildLayers(mTransaction);
 
@@ -312,7 +310,7 @@
     }
 
     @Test
-    public void testStackLayers() throws Exception {
+    public void testStackLayers() {
         final WindowState anyWindow1 = createWindow("anyWindow");
         final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
                 ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
@@ -342,7 +340,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForSysUiPanels() throws Exception {
+    public void testAssignWindowLayers_ForSysUiPanels() {
         final WindowState navBarPanel =
                 createWindow(null, TYPE_NAVIGATION_BAR_PANEL, mDisplayContent, "NavBarPanel");
         final WindowState statusBarPanel =
@@ -359,7 +357,7 @@
     }
 
     @Test
-    public void testAssignWindowLayers_ForNegativelyZOrderedSubtype() throws Exception {
+    public void testAssignWindowLayers_ForNegativelyZOrderedSubtype() {
         // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
         // then we can drop all negative layering on the windowing side.
 
@@ -376,7 +374,7 @@
     }
 
     @Test
-    public void testDockedDividerPosition() throws Exception {
+    public void testDockedDividerPosition() {
         final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
                 ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
                 "pinnedStackWindow");
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 08bc9bc..daa09f5 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -397,7 +397,19 @@
         public static final int PROPERTY_WIFI = 0x00000008;
 
         /**
-         * Call is using high definition audio.
+         * When set, the UI should indicate to the user that a call is using high definition
+         * audio.
+         * <p>
+         * The underlying {@link ConnectionService} is responsible for reporting this
+         * property.  It is important to note that this property is not intended to report the
+         * actual audio codec being used for a Call, but whether the call should be indicated
+         * to the user as high definition.
+         * <p>
+         * The Android Telephony stack reports this property for calls based on a number
+         * of factors, including which audio codec is used and whether a call is using an HD
+         * codec end-to-end.  Some mobile operators choose to suppress display of an HD indication,
+         * and in these cases this property will not be set for a call even if the underlying audio
+         * codec is in fact "high definition".
          */
         public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index d33a537..3127b35 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -676,7 +676,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelecomManager from(Context context) {
         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
     }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 4846092..8454d12 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3289,7 +3289,6 @@
             values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex());
             values.put(CDMA_ERI_ICON_MODE, state.getCdmaEriIconMode());
             values.put(IS_EMERGENCY_ONLY, state.isEmergencyOnly());
-            values.put(IS_DATA_ROAMING_FROM_REGISTRATION, state.getDataRoamingFromRegistration());
             values.put(IS_USING_CARRIER_AGGREGATION, state.isUsingCarrierAggregation());
             return values;
         }
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 79298fd..ac38efb 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -34,8 +34,8 @@
  * Received Signal Strength and Cell ID location.
  *
  * @deprecated This class should not be used by any app targeting
- *     {@link Build.VERSION_CODES.Q Android Q} or higher. Instead callers should use
- *     {@Link android.telephony.CellInfo CellInfo}.
+ *     {@link android.os.Build.VERSION_CODES#Q Android Q} or higher. Instead callers should use
+ *     {@link android.telephony.CellInfo CellInfo}.
  */
 @Deprecated
 public class NeighboringCellInfo implements Parcelable
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index c393155..b312f84 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -95,6 +95,13 @@
     @RegState
     private final int mRegState;
 
+    /**
+     * Save the {@link ServiceState.RoamingType roaming type}. it can be overridden roaming type
+     * from resource overlay or carrier config.
+     */
+    @ServiceState.RoamingType
+    private int mRoamingType;
+
     private final int mAccessNetworkTechnology;
 
     private final int mRejectCause;
@@ -140,6 +147,8 @@
         mDomain = domain;
         mTransportType = transportType;
         mRegState = regState;
+        mRoamingType = (regState == REG_STATE_ROAMING)
+                ? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
         mAccessNetworkTechnology = accessNetworkTechnology;
         mRejectCause = rejectCause;
         mAvailableServices = availableServices;
@@ -182,6 +191,7 @@
         mDomain = source.readInt();
         mTransportType = source.readInt();
         mRegState = source.readInt();
+        mRoamingType = source.readInt();
         mAccessNetworkTechnology = source.readInt();
         mRejectCause = source.readInt();
         mEmergencyOnly = source.readBoolean();
@@ -211,6 +221,31 @@
     }
 
     /**
+     * @return {@code true} if registered on roaming network, {@code false} otherwise.
+     */
+    public boolean isRoaming() {
+        return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
+    }
+
+    /**
+     * Set {@link ServiceState.RoamingType roaming type}. This could override
+     * roaming type based on resource overlay or carrier config.
+     * @hide
+     */
+    public void setRoamingType(@ServiceState.RoamingType int roamingType) {
+        mRoamingType = roamingType;
+    }
+
+    /**
+     * @return {@link ServiceState.RoamingType roaming type}. This could return
+     * overridden roaming type based on resource overlay or carrier config.
+     * @hide
+     */
+    public @ServiceState.RoamingType int getRoamingType() {
+        return mRoamingType;
+    }
+
+    /**
      * @return Whether emergency is enabled.
      */
     public boolean isEmergencyEnabled() { return mEmergencyOnly; }
@@ -280,6 +315,7 @@
                 .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
                 .append("transportType=").append(mTransportType)
                 .append(" regState=").append(regStateToString(mRegState))
+                .append(" roamingType=").append(mRoamingType)
                 .append(" accessNetworkTechnology=")
                 .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
                 .append(" rejectCause=").append(mRejectCause)
@@ -293,9 +329,9 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDomain, mTransportType, mRegState, mAccessNetworkTechnology,
-                mRejectCause, mEmergencyOnly, mAvailableServices, mCellIdentity,
-                mVoiceSpecificStates, mDataSpecificStates);
+        return Objects.hash(mDomain, mTransportType, mRegState, mRoamingType,
+                mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
+                mCellIdentity, mVoiceSpecificStates, mDataSpecificStates);
     }
 
     @Override
@@ -310,6 +346,7 @@
         return mDomain == other.mDomain
                 && mTransportType == other.mTransportType
                 && mRegState == other.mRegState
+                && mRoamingType == other.mRoamingType
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
                 && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
@@ -325,6 +362,7 @@
         dest.writeInt(mDomain);
         dest.writeInt(mTransportType);
         dest.writeInt(mRegState);
+        dest.writeInt(mRoamingType);
         dest.writeInt(mAccessNetworkTechnology);
         dest.writeInt(mRejectCause);
         dest.writeBoolean(mEmergencyOnly);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 7469186..bfbcd57 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -20,6 +20,8 @@
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -57,7 +59,7 @@
      * Normal operation condition, the phone is registered
      * with an operator either in home network or in roaming.
      */
-    public static final int STATE_IN_SERVICE = 0;
+    public static final int STATE_IN_SERVICE = TelephonyProtoEnums.SERVICE_STATE_IN_SERVICE; // 0
 
     /**
      * Phone is not registered with any operator, the phone
@@ -65,17 +67,19 @@
      * searching to registration at all, or registration is denied, or radio
      * signal is not available.
      */
-    public static final int STATE_OUT_OF_SERVICE = 1;
+    public static final int STATE_OUT_OF_SERVICE =
+            TelephonyProtoEnums.SERVICE_STATE_OUT_OF_SERVICE;  // 1
 
     /**
      * The phone is registered and locked.  Only emergency numbers are allowed. {@more}
      */
-    public static final int STATE_EMERGENCY_ONLY = 2;
+    public static final int STATE_EMERGENCY_ONLY =
+            TelephonyProtoEnums.SERVICE_STATE_EMERGENCY_ONLY;  // 2
 
     /**
      * Radio of telephony is explicitly powered off.
      */
-    public static final int STATE_POWER_OFF = 3;
+    public static final int STATE_POWER_OFF = TelephonyProtoEnums.SERVICE_STATE_POWER_OFF;  // 3
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -198,6 +202,15 @@
     private int mVoiceRegState = STATE_OUT_OF_SERVICE;
     private int mDataRegState = STATE_OUT_OF_SERVICE;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "ROAMING_TYPE_" }, value = {
+            ROAMING_TYPE_NOT_ROAMING,
+            ROAMING_TYPE_UNKNOWN,
+            ROAMING_TYPE_DOMESTIC,
+            ROAMING_TYPE_INTERNATIONAL
+    })
+    public @interface RoamingType {}
     /**
      * Roaming type
      * HOME : in home network
@@ -228,15 +241,13 @@
      */
     public static final int UNKNOWN_ID = -1;
 
-    private int mVoiceRoamingType;
-    private int mDataRoamingType;
     private String mVoiceOperatorAlphaLong;
     private String mVoiceOperatorAlphaShort;
     private String mVoiceOperatorNumeric;
     private String mDataOperatorAlphaLong;
     private String mDataOperatorAlphaShort;
     private String mDataOperatorNumeric;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private boolean mIsManualNetworkSelection;
 
     private boolean mIsEmergencyOnly;
@@ -246,9 +257,9 @@
 
     @UnsupportedAppUsage
     private boolean mCssIndicator;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private int mNetworkId;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private int mSystemId;
     @UnsupportedAppUsage
     private int mCdmaRoamingIndicator;
@@ -259,8 +270,6 @@
     @UnsupportedAppUsage
     private int mCdmaEriIconMode;
 
-    private boolean mIsDataRoamingFromRegistration;
-
     @UnsupportedAppUsage
     private boolean mIsUsingCarrierAggregation;
 
@@ -332,8 +341,6 @@
     protected void copyFrom(ServiceState s) {
         mVoiceRegState = s.mVoiceRegState;
         mDataRegState = s.mDataRegState;
-        mVoiceRoamingType = s.mVoiceRoamingType;
-        mDataRoamingType = s.mDataRoamingType;
         mVoiceOperatorAlphaLong = s.mVoiceOperatorAlphaLong;
         mVoiceOperatorAlphaShort = s.mVoiceOperatorAlphaShort;
         mVoiceOperatorNumeric = s.mVoiceOperatorNumeric;
@@ -351,7 +358,6 @@
         mCdmaEriIconIndex = s.mCdmaEriIconIndex;
         mCdmaEriIconMode = s.mCdmaEriIconMode;
         mIsEmergencyOnly = s.mIsEmergencyOnly;
-        mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
         mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
         mChannelNumber = s.mChannelNumber;
         mCellBandwidths = s.mCellBandwidths == null ? null :
@@ -367,8 +373,6 @@
     public ServiceState(Parcel in) {
         mVoiceRegState = in.readInt();
         mDataRegState = in.readInt();
-        mVoiceRoamingType = in.readInt();
-        mDataRoamingType = in.readInt();
         mVoiceOperatorAlphaLong = in.readString();
         mVoiceOperatorAlphaShort = in.readString();
         mVoiceOperatorNumeric = in.readString();
@@ -386,7 +390,6 @@
         mCdmaEriIconIndex = in.readInt();
         mCdmaEriIconMode = in.readInt();
         mIsEmergencyOnly = in.readInt() != 0;
-        mIsDataRoamingFromRegistration = in.readInt() != 0;
         mIsUsingCarrierAggregation = in.readInt() != 0;
         mLteEarfcnRsrpBoost = in.readInt();
         mNetworkRegistrationStates = new ArrayList<>();
@@ -398,8 +401,6 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mVoiceRegState);
         out.writeInt(mDataRegState);
-        out.writeInt(mVoiceRoamingType);
-        out.writeInt(mDataRoamingType);
         out.writeString(mVoiceOperatorAlphaLong);
         out.writeString(mVoiceOperatorAlphaShort);
         out.writeString(mVoiceOperatorNumeric);
@@ -417,7 +418,6 @@
         out.writeInt(mCdmaEriIconIndex);
         out.writeInt(mCdmaEriIconMode);
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
-        out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
         out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
         out.writeInt(mLteEarfcnRsrpBoost);
         out.writeList(mNetworkRegistrationStates);
@@ -457,7 +457,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getVoiceRegState() {
         return mVoiceRegState;
     }
@@ -472,7 +472,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getDataRegState() {
         return mDataRegState;
     }
@@ -533,19 +533,23 @@
      * @return roaming status
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public boolean getVoiceRoaming() {
-        return mVoiceRoamingType != ROAMING_TYPE_NOT_ROAMING;
+        return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
     }
-
     /**
      * Get current voice network roaming type
      * @return roaming type
      * @hide
      */
     @UnsupportedAppUsage
-    public int getVoiceRoamingType() {
-        return mVoiceRoamingType;
+    public @RoamingType int getVoiceRoamingType() {
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState != null) {
+            return regState.getRoamingType();
+        }
+        return ROAMING_TYPE_NOT_ROAMING;
     }
 
     /**
@@ -553,21 +557,9 @@
      * @return roaming type
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public boolean getDataRoaming() {
-        return mDataRoamingType != ROAMING_TYPE_NOT_ROAMING;
-    }
-
-    /**
-     * Set whether data network registration state is roaming
-     *
-     * This should only be set to the roaming value received
-     * once the data registration phase has completed.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void setDataRoamingFromRegistration(boolean dataRoaming) {
-        mIsDataRoamingFromRegistration = dataRoaming;
+        return getDataRoamingType() != ROAMING_TYPE_NOT_ROAMING;
     }
 
     /**
@@ -576,7 +568,12 @@
      * @hide
      */
     public boolean getDataRoamingFromRegistration() {
-        return mIsDataRoamingFromRegistration;
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState != null) {
+            return (regState.getRegState() == NetworkRegistrationState.REG_STATE_ROAMING);
+        }
+        return false;
     }
 
     /**
@@ -585,8 +582,13 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public int getDataRoamingType() {
-        return mDataRoamingType;
+    public @RoamingType int getDataRoamingType() {
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState != null) {
+            return regState.getRoamingType();
+        }
+        return ROAMING_TYPE_NOT_ROAMING;
     }
 
     /**
@@ -759,8 +761,6 @@
         return Objects.hash(
                 mVoiceRegState,
                 mDataRegState,
-                mVoiceRoamingType,
-                mDataRoamingType,
                 mChannelNumber,
                 mCellBandwidths,
                 mVoiceOperatorAlphaLong,
@@ -780,7 +780,6 @@
                 mCdmaEriIconIndex,
                 mCdmaEriIconMode,
                 mIsEmergencyOnly,
-                mIsDataRoamingFromRegistration,
                 mIsUsingCarrierAggregation,
                 mLteEarfcnRsrpBoost,
                 mNetworkRegistrationStates);
@@ -794,8 +793,6 @@
         return (mVoiceRegState == s.mVoiceRegState
                 && mDataRegState == s.mDataRegState
                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
-                && mVoiceRoamingType == s.mVoiceRoamingType
-                && mDataRoamingType == s.mDataRoamingType
                 && mChannelNumber == s.mChannelNumber
                 && Arrays.equals(mCellBandwidths, s.mCellBandwidths)
                 && equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
@@ -813,7 +810,6 @@
                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
                         s.mCdmaDefaultRoamingIndicator)
                 && mIsEmergencyOnly == s.mIsEmergencyOnly
-                && mIsDataRoamingFromRegistration == s.mIsDataRoamingFromRegistration
                 && mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
                 && (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
                         s.mNetworkRegistrationStates != null &&
@@ -933,8 +929,6 @@
             .append(", mChannelNumber=").append(mChannelNumber)
             .append(", duplexMode()=").append(getDuplexMode())
             .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
-            .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
-            .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
             .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
             .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
             .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
@@ -951,7 +945,6 @@
             .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
             .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
             .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
-            .append(", mIsDataRoamingFromRegistration=").append(mIsDataRoamingFromRegistration)
             .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
             .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
             .append(", mNetworkRegistrationStates=").append(mNetworkRegistrationStates)
@@ -962,8 +955,6 @@
         if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setNullState=" + state);
         mVoiceRegState = state;
         mDataRegState = state;
-        mVoiceRoamingType = ROAMING_TYPE_NOT_ROAMING;
-        mDataRoamingType = ROAMING_TYPE_NOT_ROAMING;
         mChannelNumber = -1;
         mCellBandwidths = new int[0];
         mVoiceOperatorAlphaLong = null;
@@ -983,7 +974,6 @@
         mCdmaEriIconIndex = -1;
         mCdmaEriIconMode = -1;
         mIsEmergencyOnly = false;
-        mIsDataRoamingFromRegistration = false;
         mIsUsingCarrierAggregation = false;
         mLteEarfcnRsrpBoost = 0;
         mNetworkRegistrationStates = new ArrayList<>();
@@ -1029,32 +1019,50 @@
     }
 
     public void setRoaming(boolean roaming) {
-        mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
-        mDataRoamingType = mVoiceRoamingType;
+        setVoiceRoaming(roaming);
+        setDataRoaming(roaming);
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public void setVoiceRoaming(boolean roaming) {
-        mVoiceRoamingType = (roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
+        setVoiceRoamingType(roaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
     @UnsupportedAppUsage
-    public void setVoiceRoamingType(int type) {
-        mVoiceRoamingType = type;
+    public void setVoiceRoamingType(@RoamingType int type) {
+        NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState == null) {
+            regState = new NetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+                    ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
+                    false, null, null);
+            addNetworkRegistrationState(regState);
+        }
+        regState.setRoamingType(type);
     }
 
     /** @hide */
     @UnsupportedAppUsage
     public void setDataRoaming(boolean dataRoaming) {
-        mDataRoamingType = (dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
+        setDataRoamingType(dataRoaming ? ROAMING_TYPE_UNKNOWN : ROAMING_TYPE_NOT_ROAMING);
     }
 
     /** @hide */
     @UnsupportedAppUsage
-    public void setDataRoamingType(int type) {
-        mDataRoamingType = type;
+    public void setDataRoamingType(@RoamingType int type) {
+        NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState == null) {
+            regState = new NetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+                    ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN, 0,
+                    false, null, null);
+            addNetworkRegistrationState(regState);
+        }
+        regState.setRoamingType(type);
     }
 
     /**
@@ -1166,30 +1174,10 @@
      */
     @UnsupportedAppUsage
     private void setFromNotifierBundle(Bundle m) {
-        mVoiceRegState = m.getInt("voiceRegState");
-        mDataRegState = m.getInt("dataRegState");
-        mVoiceRoamingType = m.getInt("voiceRoamingType");
-        mDataRoamingType = m.getInt("dataRoamingType");
-        mVoiceOperatorAlphaLong = m.getString("operator-alpha-long");
-        mVoiceOperatorAlphaShort = m.getString("operator-alpha-short");
-        mVoiceOperatorNumeric = m.getString("operator-numeric");
-        mDataOperatorAlphaLong = m.getString("data-operator-alpha-long");
-        mDataOperatorAlphaShort = m.getString("data-operator-alpha-short");
-        mDataOperatorNumeric = m.getString("data-operator-numeric");
-        mIsManualNetworkSelection = m.getBoolean("manual");
-        mRilVoiceRadioTechnology = m.getInt("radioTechnology");
-        mRilDataRadioTechnology = m.getInt("dataRadioTechnology");
-        mCssIndicator = m.getBoolean("cssIndicator");
-        mNetworkId = m.getInt("networkId");
-        mSystemId = m.getInt("systemId");
-        mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
-        mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
-        mIsEmergencyOnly = m.getBoolean("emergencyOnly");
-        mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
-        mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
-        mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
-        mChannelNumber = m.getInt("ChannelNumber");
-        mCellBandwidths = m.getIntArray("CellBandwidths");
+        ServiceState ssFromBundle = m.getParcelable(Intent.EXTRA_SERVICE_STATE);
+        if (ssFromBundle != null) {
+            copyFrom(ssFromBundle);
+        }
     }
 
     /**
@@ -1200,10 +1188,13 @@
      */
     @UnsupportedAppUsage
     public void fillInNotifierBundle(Bundle m) {
+        m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
+        // serviceState already consists of below entries.
+        // for backward compatibility, we continue fill in below entries.
         m.putInt("voiceRegState", mVoiceRegState);
         m.putInt("dataRegState", mDataRegState);
-        m.putInt("voiceRoamingType", mVoiceRoamingType);
-        m.putInt("dataRoamingType", mDataRoamingType);
+        m.putInt("dataRoamingType", getDataRoamingType());
+        m.putInt("voiceRoamingType", getVoiceRoamingType());
         m.putString("operator-alpha-long", mVoiceOperatorAlphaLong);
         m.putString("operator-alpha-short", mVoiceOperatorAlphaShort);
         m.putString("operator-numeric", mVoiceOperatorNumeric);
@@ -1219,7 +1210,7 @@
         m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
         m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
         m.putBoolean("emergencyOnly", mIsEmergencyOnly);
-        m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
+        m.putBoolean("isDataRoamingFromRegistration", getDataRoamingFromRegistration());
         m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
         m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
         m.putInt("ChannelNumber", mChannelNumber);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a264707..40ba2b6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -32,12 +32,14 @@
 import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
 import android.app.PendingIntent;
+import android.app.job.JobService;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.net.INetworkPolicyManager;
 import android.net.NetworkCapabilities;
 import android.net.Uri;
@@ -116,6 +118,52 @@
     @UnsupportedAppUsage
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
+
+    /**
+     * Generates a content {@link Uri} used to receive updates on simInfo change
+     * on the given subscriptionId
+     * @param subscriptionId the subscriptionId to receive updates on
+     * @return the Uri used to observe carrier identity changes
+     * @hide
+     */
+    public static Uri getUriForSubscriptionId(int subscriptionId) {
+        return Uri.withAppendedPath(CONTENT_URI, String.valueOf(subscriptionId));
+    }
+
+    /**
+     * A content {@link Uri} used to receive updates on wfc enabled user setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription wfc enabled {@link SubscriptionManager#WFC_IMS_ENABLED}
+     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
+
+    /**
+     * A content {@link Uri} used to receive updates on enhanced 4g user setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription enhanced 4G enabled {@link SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri ENHANCED_4G_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+            CONTENT_URI, "enhanced_4g");
+
+
     /**
      * TelephonyProvider unique key column name is the subscription id.
      * <P>Type: TEXT (String)</P>
@@ -1321,7 +1369,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static int getPhoneId(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1603,7 +1651,7 @@
      * Check if the subscription ID is usable.
      *
      * A usable subscription ID has a valid value except some special values such as
-     * {@link DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
+     * {@link #DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
      *
      * @param subscriptionId the subscription ID
      * @return {@code true} if the subscription ID is usable; {@code false} otherwise.
@@ -1617,7 +1665,7 @@
      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static boolean isUsableSubIdValue(int subId) {
         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
     }
@@ -1635,7 +1683,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
         int[] subIds = SubscriptionManager.getSubId(phoneId);
         if (subIds != null && subIds.length > 0) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c5e4707..b6d728e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -60,6 +60,7 @@
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.ims.internal.IImsServiceFeatureCallback;
@@ -229,7 +230,8 @@
 
     /** @hide
     /* @deprecated - use getSystemService as described above */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelephonyManager getDefault() {
         return sInstance;
     }
@@ -318,7 +320,7 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelephonyManager from(Context context) {
         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
     }
@@ -1905,7 +1907,7 @@
      * @param subId
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getNetworkOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
@@ -1933,7 +1935,7 @@
      * @param subId
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getNetworkOperator(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getNetworkOperatorForPhone(phoneId);
@@ -2257,7 +2259,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getDataNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2293,7 +2295,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getVoiceNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2446,39 +2448,46 @@
      *
      * These are the ordinal value of IccCardConstants.State.
      */
-    public static final int SIM_STATE_UNKNOWN = 0;
+
+    public static final int SIM_STATE_UNKNOWN = TelephonyProtoEnums.SIM_STATE_UNKNOWN;  // 0
     /** SIM card state: no SIM card is available in the device */
-    public static final int SIM_STATE_ABSENT = 1;
+    public static final int SIM_STATE_ABSENT = TelephonyProtoEnums.SIM_STATE_ABSENT;  // 1
     /** SIM card state: Locked: requires the user's SIM PIN to unlock */
-    public static final int SIM_STATE_PIN_REQUIRED = 2;
+    public static final int SIM_STATE_PIN_REQUIRED =
+            TelephonyProtoEnums.SIM_STATE_PIN_REQUIRED;  // 2
     /** SIM card state: Locked: requires the user's SIM PUK to unlock */
-    public static final int SIM_STATE_PUK_REQUIRED = 3;
+    public static final int SIM_STATE_PUK_REQUIRED =
+            TelephonyProtoEnums.SIM_STATE_PUK_REQUIRED;  // 3
     /** SIM card state: Locked: requires a network PIN to unlock */
-    public static final int SIM_STATE_NETWORK_LOCKED = 4;
+    public static final int SIM_STATE_NETWORK_LOCKED =
+            TelephonyProtoEnums.SIM_STATE_NETWORK_LOCKED;  // 4
     /** SIM card state: Ready */
-    public static final int SIM_STATE_READY = 5;
+    public static final int SIM_STATE_READY = TelephonyProtoEnums.SIM_STATE_READY;  // 5
     /** SIM card state: SIM Card is NOT READY */
-    public static final int SIM_STATE_NOT_READY = 6;
+    public static final int SIM_STATE_NOT_READY = TelephonyProtoEnums.SIM_STATE_NOT_READY;  // 6
     /** SIM card state: SIM Card Error, permanently disabled */
-    public static final int SIM_STATE_PERM_DISABLED = 7;
+    public static final int SIM_STATE_PERM_DISABLED =
+            TelephonyProtoEnums.SIM_STATE_PERM_DISABLED;  // 7
     /** SIM card state: SIM Card Error, present but faulty */
-    public static final int SIM_STATE_CARD_IO_ERROR = 8;
+    public static final int SIM_STATE_CARD_IO_ERROR =
+            TelephonyProtoEnums.SIM_STATE_CARD_IO_ERROR;  // 8
     /** SIM card state: SIM Card restricted, present but not usable due to
      * carrier restrictions.
      */
-    public static final int SIM_STATE_CARD_RESTRICTED = 9;
+    public static final int SIM_STATE_CARD_RESTRICTED =
+            TelephonyProtoEnums.SIM_STATE_CARD_RESTRICTED;  // 9
     /**
      * SIM card state: Loaded: SIM card applications have been loaded
      * @hide
      */
     @SystemApi
-    public static final int SIM_STATE_LOADED = 10;
+    public static final int SIM_STATE_LOADED = TelephonyProtoEnums.SIM_STATE_LOADED;  // 10
     /**
      * SIM card state: SIM Card is present
      * @hide
      */
     @SystemApi
-    public static final int SIM_STATE_PRESENT = 11;
+    public static final int SIM_STATE_PRESENT = TelephonyProtoEnums.SIM_STATE_PRESENT;  // 11
 
     /**
      * Extra included in {@link #ACTION_SIM_CARD_STATE_CHANGED} and
@@ -2769,7 +2778,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperator(int subId) {
         return getSimOperatorNumeric(subId);
     }
@@ -2783,7 +2792,7 @@
      * @see #getSimState
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumeric() {
         int subId = mSubId;
         if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2812,7 +2821,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumeric(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNumericForPhone(phoneId);
@@ -2826,7 +2835,7 @@
      * @param phoneId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumericForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -2853,7 +2862,7 @@
      * @param subId for which SimOperatorName is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNameForPhone(phoneId);
@@ -2883,7 +2892,7 @@
      * @param subId for which SimCountryIso is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimCountryIso(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimCountryIsoForPhone(phoneId);
@@ -3095,7 +3104,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSubscriberId(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3480,7 +3489,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getMsisdn(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4413,7 +4422,7 @@
    /**
     * @hide
     */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private ITelephony getITelephony() {
         return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
     }
@@ -5395,7 +5404,7 @@
     @UnsupportedAppUsage
     public static String getTelephonyProperty(String property, String defaultVal) {
         String propVal = SystemProperties.get(property);
-        return propVal == null ? defaultVal : propVal;
+        return TextUtils.isEmpty(propVal) ? defaultVal : propVal;
     }
 
     /** @hide */
@@ -7937,7 +7946,7 @@
      * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public ServiceState getServiceStateForSubscriber(int subId) {
         try {
             ITelephony service = getITelephony();
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 8379f8c..eb144f9 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -80,7 +80,7 @@
      */
     public static final int TYPE_ALL = ApnTypes.ALL;
     /** APN type for default data traffic. */
-    public static final int TYPE_DEFAULT = ApnTypes.DEFAULT;
+    public static final int TYPE_DEFAULT = ApnTypes.DEFAULT | ApnTypes.HIPRI;
     /** APN type for MMS traffic. */
     public static final int TYPE_MMS = ApnTypes.MMS;
     /** APN type for SUPL assisted GPS. */
@@ -979,7 +979,7 @@
             return false;
         }
         // DEFAULT can handle HIPRI.
-        if (hasApnType(type) || (type == TYPE_HIPRI && hasApnType(TYPE_DEFAULT))) {
+        if (hasApnType(type)) {
             return true;
         }
         return false;
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 3a26350..cb8269e 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -420,6 +420,7 @@
     int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 201;
     int RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA = 202;
     int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 203;
+    int RIL_REQUEST_SET_PREFERRED_DATA_MODEM = 204;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index dac7e04..9730ebc 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -32,6 +32,7 @@
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -43,6 +44,10 @@
 
     private static final boolean DBG = false;
 
+    // When set to true this flag will treat all apps that fail the device identifier check as
+    // though they are targeting pre-Q and return dummy data instead of throwing a SecurityException
+    private static final boolean RELAX_DEVICE_IDENTIFIER_CHECK = true;
+
     private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
             ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
 
@@ -275,31 +280,41 @@
      */
     private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
             int uid, String callingPackage, String message) {
-        if (callingPackage != null) {
-            try {
-                // if the target SDK is pre-Q then check if the calling package would have
-                // previously had access to device identifiers.
-                ApplicationInfo callingPackageInfo = context.getPackageManager().getApplicationInfo(
-                        callingPackage, 0);
-                if (callingPackageInfo != null
-                        && callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
-                    if (context.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid,
-                            uid) == PackageManager.PERMISSION_GRANTED) {
-                        return false;
+        // if the device identifier check is relaxed then just return false to return dummy data to
+        // the caller instead of throwing a SecurityException for apps targeting Q+.
+        if (RELAX_DEVICE_IDENTIFIER_CHECK) {
+            Log.wtf(LOG_TAG,
+                    "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
+            return false;
+        } else {
+            if (callingPackage != null) {
+                try {
+                    // if the target SDK is pre-Q then check if the calling package would have
+                    // previously had access to device identifiers.
+                    ApplicationInfo callingPackageInfo =
+                            context.getPackageManager().getApplicationInfo(
+                                    callingPackage, 0);
+                    if (callingPackageInfo != null
+                            && callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
+                        if (context.checkPermission(android.Manifest.permission.READ_PHONE_STATE,
+                                pid,
+                                uid) == PackageManager.PERMISSION_GRANTED) {
+                            return false;
+                        }
+                        if (SubscriptionManager.isValidSubscriptionId(subId)
+                                && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
+                                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                            return false;
+                        }
                     }
-                    if (SubscriptionManager.isValidSubscriptionId(subId)
-                            && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
-                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                        return false;
-                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    // If the application info for the calling package could not be found then
+                    // default to throwing the SecurityException.
                 }
-            } catch (PackageManager.NameNotFoundException e) {
-                // If the application info for the calling package could not be found then default
-                // to throwing the SecurityException.
             }
+            throw new SecurityException(message + ": The user " + uid + " does not have the "
+                    + "READ_PRIVILEGED_PHONE_STATE permission to access the device identifiers");
         }
-        throw new SecurityException(message + ": The user " + uid + " does not have the "
-                + "READ_PRIVILEGED_PHONE_STATE permission to access the device identifiers");
     }
 
     /**
diff --git a/test-mock/api/system-current.txt b/test-mock/api/system-current.txt
index 3bd3d68..2b968ae 100644
--- a/test-mock/api/system-current.txt
+++ b/test-mock/api/system-current.txt
@@ -29,6 +29,7 @@
     method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
+    method public java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String);
     method public void setUpdateAvailable(java.lang.String, boolean);
     method public boolean updateIntentVerificationStatusAsUser(java.lang.String, int, int);
     method public void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
index 4c68c8b..94294f6 100644
--- a/tests/ActivityTests/Android.mk
+++ b/tests/ActivityTests/Android.mk
@@ -10,9 +10,5 @@
 LOCAL_CERTIFICATE := platform
 
 LOCAL_USE_AAPT2 := true
-# Disable AAPT2 manifest checks to fix:
-# frameworks/base/tests/ActivityTests/AndroidManifest.xml:42: error: unexpected element <preferred> found in <manifest><application><activity>.
-# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
-LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index c225e17..a6c21db 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -7,7 +7,6 @@
 
 LOCAL_JAVA_LIBRARIES := \
     android.test.runner \
-    conscrypt \
     android.test.base \
 
 LOCAL_STATIC_JAVA_LIBRARIES := junit
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 750e2fb..132135d 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -63,7 +63,8 @@
     libunwindstack \
     libutilscallstack \
     libziparchive \
-    libz
+    libz \
+    netd_aidl_interface-cpp
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
@@ -92,7 +93,8 @@
   liblog \
   libcutils \
   libnativehelper \
-  libnetdaidl
+  libnetdaidl \
+  netd_aidl_interface-cpp
 
 LOCAL_STATIC_LIBRARIES := \
   libpcap \
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 954f1ed..3ea1755 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -46,7 +46,7 @@
   IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {}
 
   virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
-                            IArchiveWriter* writer) = 0;
+                            IArchiveWriter* writer, uint32_t compression_flags) = 0;
   virtual bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) = 0;
   virtual bool SerializeFile(FileReference* file, IArchiveWriter* writer) = 0;
 
@@ -59,7 +59,10 @@
 
 bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer* serializer,
                 IArchiveWriter* writer) {
-  if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer)) {
+  io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
+  if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer,
+                                (manifest != nullptr && manifest->WasCompressed())
+                                    ? ArchiveEntry::kCompress : 0u)) {
     context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
                                      << "failed to serialize AndroidManifest.xml");
     return false;
@@ -133,7 +136,7 @@
       : IApkSerializer(context, source), tableFlattenerOptions_(options) {}
 
   bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
-                    IArchiveWriter* writer) override {
+                    IArchiveWriter* writer, uint32_t compression_flags) override {
     BigBuffer buffer(4096);
     XmlFlattenerOptions options = {};
     options.use_utf16 = utf16;
@@ -144,8 +147,7 @@
     }
 
     io::BigBufferInputStream input_stream(&buffer);
-    return io::CopyInputStreamToArchive(context_, &input_stream, path, ArchiveEntry::kCompress,
-                                        writer);
+    return io::CopyInputStreamToArchive(context_, &input_stream, path, compression_flags, writer);
   }
 
   bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
@@ -186,7 +188,8 @@
         return false;
       }
 
-      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
+      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer,
+                        file->file->WasCompressed() ? ArchiveEntry::kCompress : 0u)) {
         context_->GetDiagnostics()->Error(DiagMessage(source_)
                                           << "failed to serialize to binary XML: " << *file->path);
         return false;
@@ -216,10 +219,10 @@
       : IApkSerializer(context, source) {}
 
   bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
-                    IArchiveWriter* writer) override {
+                    IArchiveWriter* writer, uint32_t compression_flags) override {
     pb::XmlNode pb_node;
     SerializeXmlResourceToPb(*xml, &pb_node);
-    return io::CopyProtoToArchive(context_, &pb_node, path, ArchiveEntry::kCompress, writer);
+    return io::CopyProtoToArchive(context_, &pb_node, path, compression_flags, writer);
   }
 
   bool SerializeTable(ResourceTable* table, IArchiveWriter* writer) override {
@@ -246,7 +249,8 @@
         return false;
       }
 
-      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer)) {
+      if (!SerializeXml(xml.get(), *file->path, false /*utf16*/, writer,
+                        file->file->WasCompressed() ? ArchiveEntry::kCompress : 0u)) {
         context_->GetDiagnostics()->Error(DiagMessage(source_)
                                           << "failed to serialize to proto XML: " << *file->path);
         return false;
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 4245700..d1f42f8 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -251,7 +251,7 @@
     }
     atomDecl->fields.push_back(atField);
 
-    if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
+    if (field->options().GetExtension(os::statsd::state_field_option).option() ==
         os::statsd::StateField::PRIMARY) {
         if (javaType == JAVA_TYPE_UNKNOWN ||
             javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
@@ -261,7 +261,7 @@
         atomDecl->primaryFields.push_back(it->first);
     }
 
-    if (field->options().GetExtension(os::statsd::stateFieldOption).option() ==
+    if (field->options().GetExtension(os::statsd::state_field_option).option() ==
         os::statsd::StateField::EXCLUSIVE) {
         if (javaType == JAVA_TYPE_UNKNOWN ||
             javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index 264a865..f635974 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -127,33 +127,33 @@
 // The atom has only primary field but no exclusive state field.
 message BadStateAtom1 {
     optional int32 uid = 1
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
 }
 
 // Only primative types can be annotated.
 message BadStateAtom2 {
     repeated android.os.statsd.AttributionNode attribution = 1
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
     optional int32 state = 2
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
 }
 
 // Having 2 exclusive state field in the atom means the atom is badly designed.
 // E.g., putting bluetooth state and wifi state in the same atom.
 message BadStateAtom3 {
     optional int32 uid = 1
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
     optional int32 state = 2
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
     optional int32 state2 = 3
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
 }
 
 message GoodStateAtom1 {
     optional int32 uid = 1
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
     optional int32 state = 2
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
 }
 
 // Atoms can have exclusive state field, but no primary field. That means
@@ -161,16 +161,16 @@
 message GoodStateAtom2 {
     optional int32 uid = 1;
     optional int32 state = 2
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
 }
 
 // We can have more than one primary fields. That means their combination is a
 // primary key.
 message GoodStateAtom3 {
     optional int32 uid = 1
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
     optional int32 tid = 2
-            [(android.os.statsd.stateFieldOption).option = PRIMARY];
+            [(android.os.statsd.state_field_option).option = PRIMARY];
     optional int32 state = 3
-            [(android.os.statsd.stateFieldOption).option = EXCLUSIVE];
+            [(android.os.statsd.state_field_option).option = EXCLUSIVE];
 }
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java b/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java
deleted file mode 100644
index f5cad13..0000000
--- a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A class representing wifi wake reason accounting.
- */
-
-/** @hide */
-public class WifiWakeReasonAndCounts implements Parcelable {
-    private static final String TAG = "WifiWakeReasonAndCounts";
-    /**
-     * Wlan can wake host, only when it is cmd/event, local driver-fw
-     * functions(non-data, non cmd/event) and rx data.The first packet
-     * from wlan that woke up a sleep host is what is accounted here.
-     * Total wlan wake to application processor would be:
-     * [cmdEventWake + driverFwLocalWake + totalRxDataWake]
-     * A further classification is provided for identifying the reasons
-     * for wakeup.
-     */
-    public int totalCmdEventWake;
-    public int totalDriverFwLocalWake;
-    public int totalRxDataWake;
-
-    public int rxUnicast;
-    public int rxMulticast;
-    public int rxBroadcast;
-
-    public int icmp;
-    public int icmp6;
-    public int icmp6Ra;
-    public int icmp6Na;
-    public int icmp6Ns;
-
-    public int ipv4RxMulticast;
-    public int ipv6Multicast;
-    public int otherRxMulticast;
-    public int[] cmdEventWakeCntArray;
-    public int[] driverFWLocalWakeCntArray;
-
-    /* {@hide} */
-    public WifiWakeReasonAndCounts () {
-    }
-
-    @Override
-    /* {@hide} */
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(" totalCmdEventWake ").append(totalCmdEventWake);
-        sb.append(" totalDriverFwLocalWake ").append(totalDriverFwLocalWake);
-        sb.append(" totalRxDataWake ").append(totalRxDataWake);
-
-        sb.append(" rxUnicast ").append(rxUnicast);
-        sb.append(" rxMulticast ").append(rxMulticast);
-        sb.append(" rxBroadcast ").append(rxBroadcast);
-
-        sb.append(" icmp ").append(icmp);
-        sb.append(" icmp6 ").append(icmp6);
-        sb.append(" icmp6Ra ").append(icmp6Ra);
-        sb.append(" icmp6Na ").append(icmp6Na);
-        sb.append(" icmp6Ns ").append(icmp6Ns);
-
-        sb.append(" ipv4RxMulticast ").append(ipv4RxMulticast);
-        sb.append(" ipv6Multicast ").append(ipv6Multicast);
-        sb.append(" otherRxMulticast ").append(otherRxMulticast);
-        for (int i = 0; i < cmdEventWakeCntArray.length; i++) {
-            sb.append(" cmdEventWakeCntArray[" + i + "] " + cmdEventWakeCntArray[i]);
-        }
-        for (int i = 0; i < driverFWLocalWakeCntArray.length; i++) {
-            sb.append(" driverFWLocalWakeCntArray[" + i + "] " + driverFWLocalWakeCntArray[i]);
-        }
-
-        return sb.toString();
-    }
-
-    /* Implement the Parcelable interface
-     * {@hide}
-     */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /* Implement the Parcelable interface
-     * {@hide}
-     */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(totalCmdEventWake);
-        dest.writeInt(totalDriverFwLocalWake);
-        dest.writeInt(totalRxDataWake);
-
-        dest.writeInt(rxUnicast);
-        dest.writeInt(rxMulticast);
-        dest.writeInt(rxBroadcast);
-
-        dest.writeInt(icmp);
-        dest.writeInt(icmp6);
-        dest.writeInt(icmp6Ra);
-        dest.writeInt(icmp6Na);
-        dest.writeInt(icmp6Ns);
-
-        dest.writeInt(ipv4RxMulticast);
-        dest.writeInt(ipv6Multicast);
-        dest.writeInt(otherRxMulticast);
-        dest.writeIntArray(cmdEventWakeCntArray);
-        dest.writeIntArray(driverFWLocalWakeCntArray);
-    }
-
-    /* Implement the Parcelable interface
-     * {@hide}
-     */
-    public static final Creator<WifiWakeReasonAndCounts> CREATOR =
-        new Creator<WifiWakeReasonAndCounts>() {
-            public WifiWakeReasonAndCounts createFromParcel(Parcel in) {
-                WifiWakeReasonAndCounts counts = new WifiWakeReasonAndCounts();
-                counts.totalCmdEventWake = in.readInt();
-                counts.totalDriverFwLocalWake = in.readInt();
-                counts.totalRxDataWake = in.readInt();
-
-                counts.rxUnicast = in.readInt();
-                counts.rxMulticast = in.readInt();
-                counts.rxBroadcast = in.readInt();
-
-                counts.icmp = in.readInt();
-                counts.icmp6 = in.readInt();
-                counts.icmp6Ra = in.readInt();
-                counts.icmp6Na = in.readInt();
-                counts.icmp6Ns = in.readInt();
-
-                counts.ipv4RxMulticast = in.readInt();
-                counts.ipv6Multicast = in.readInt();
-                counts.otherRxMulticast = in.readInt();
-                in.readIntArray(counts.cmdEventWakeCntArray);
-                in.readIntArray(counts.driverFWLocalWakeCntArray);
-                return counts;
-            }
-            /* Implement the Parcelable interface
-             * {@hide}
-             */
-            @Override
-            public WifiWakeReasonAndCounts[] newArray(int size) {
-                return new WifiWakeReasonAndCounts[size];
-            }
-        };
-}
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index b4dfac6..6076175 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -102,6 +102,12 @@
     public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14;
 
     /**
+     * The reason code for provisioning failure when the status of a SOAP message is not the
+     * expected message status.
+     */
+    public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15;
+
+    /**
      * The status code for provisioning flow to indicate connecting to OSU AP
      */
     public static final int OSU_STATUS_AP_CONNECTING = 1;
@@ -147,6 +153,11 @@
     public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9;
 
     /**
+     * The status code for provisioning flow to indicate starting the third SOAP exchange.
+     */
+    public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10;
+
+    /**
      * Provisioning status for OSU failure
      *
      * @param status indicates error condition
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
index 5c9df6a..c7993e3 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java
@@ -189,8 +189,7 @@
         Map<String, Long> homeNetworkIds = new HashMap<>();
         byte[] rawSsidBytes = new byte[33];
         Arrays.fill(rawSsidBytes, (byte) 'a');
-        homeNetworkIds.put(
-                StringFactory.newStringFromBytes(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L);
+        homeNetworkIds.put(new String(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L);
         homeSp.setHomeNetworkIds(homeNetworkIds);
         assertFalse(homeSp.validate());
     }