Merge "Do not mark in-process NetworkStack as persistent" into qt-dev
diff --git a/api/current.txt b/api/current.txt
index 54fb459..3ec7f44 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -220,12 +220,6 @@
 
   public static final class R.attr {
     ctor public R.attr();
-    field public static final int __removed1 = 16844185; // 0x1010599
-    field public static final int __removed2 = 16844186; // 0x101059a
-    field public static final int __removed3 = 16844187; // 0x101059b
-    field public static final int __removed4 = 16844188; // 0x101059c
-    field public static final int __removed5 = 16844189; // 0x101059d
-    field public static final int __removed6 = 16844182; // 0x1010596
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -284,7 +278,7 @@
     field public static final int alertDialogTheme = 16843529; // 0x1010309
     field public static final int alignmentMode = 16843642; // 0x101037a
     field public static final int allContactsName = 16843468; // 0x10102cc
-    field public static final int allowAudioPlaybackCapture = 16844199; // 0x10105a7
+    field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
     field public static final int allowEmbedded = 16843765; // 0x10103f5
@@ -572,8 +566,8 @@
     field public static final int endX = 16844050; // 0x1010512
     field public static final int endY = 16844051; // 0x1010513
     field @Deprecated public static final int endYear = 16843133; // 0x101017d
-    field public static final int enforceNavigationBarContrast = 16844203; // 0x10105ab
-    field public static final int enforceStatusBarContrast = 16844202; // 0x10105aa
+    field public static final int enforceNavigationBarContrast = 16844293; // 0x1010605
+    field public static final int enforceStatusBarContrast = 16844292; // 0x1010604
     field public static final int enterFadeDuration = 16843532; // 0x101030c
     field public static final int entries = 16842930; // 0x10100b2
     field public static final int entryValues = 16843256; // 0x10101f8
@@ -646,10 +640,10 @@
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
     field public static final int forceDarkAllowed = 16844172; // 0x101058c
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
-    field public static final int forceUriPermissions = 16844197; // 0x10105a5
+    field public static final int forceUriPermissions = 16844191; // 0x101059f
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
-    field public static final int foregroundServiceType = 16844191; // 0x101059f
+    field public static final int foregroundServiceType = 16844185; // 0x1010599
     field public static final int foregroundTint = 16843885; // 0x101046d
     field public static final int foregroundTintMode = 16843886; // 0x101046e
     field public static final int format = 16843013; // 0x1010105
@@ -707,7 +701,7 @@
     field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
     field public static final int hardwareAccelerated = 16843475; // 0x10102d3
     field public static final int hasCode = 16842764; // 0x101000c
-    field public static final int hasFragileUserData = 16844192; // 0x10105a0
+    field public static final int hasFragileUserData = 16844186; // 0x101059a
     field @Deprecated public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
     field public static final int headerBackground = 16843055; // 0x101012f
     field @Deprecated public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
@@ -735,7 +729,7 @@
     field public static final int iconTintMode = 16844127; // 0x101055f
     field public static final int iconifiedByDefault = 16843514; // 0x10102fa
     field public static final int id = 16842960; // 0x10100d0
-    field public static final int identifier = 16844204; // 0x10105ac
+    field public static final int identifier = 16844294; // 0x1010606
     field public static final int ignoreGravity = 16843263; // 0x10101ff
     field public static final int imageButtonStyle = 16842866; // 0x1010072
     field public static final int imageWellStyle = 16842867; // 0x1010073
@@ -767,7 +761,7 @@
     field public static final int indicatorRight = 16843022; // 0x101010e
     field public static final int indicatorStart = 16843729; // 0x10103d1
     field public static final int inflatedId = 16842995; // 0x10100f3
-    field public static final int inheritShowWhenLocked = 16844194; // 0x10105a2
+    field public static final int inheritShowWhenLocked = 16844188; // 0x101059c
     field public static final int initOrder = 16842778; // 0x101001a
     field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
     field public static final int initialLayout = 16843345; // 0x1010251
@@ -944,7 +938,7 @@
     field public static final int menuCategory = 16843230; // 0x10101de
     field public static final int mimeType = 16842790; // 0x1010026
     field public static final int min = 16844089; // 0x1010539
-    field public static final int minAspectRatio = 16844193; // 0x10105a1
+    field public static final int minAspectRatio = 16844187; // 0x101059b
     field public static final int minDate = 16843583; // 0x101033f
     field public static final int minEms = 16843098; // 0x101015a
     field public static final int minHeight = 16843072; // 0x1010140
@@ -1125,7 +1119,7 @@
     field public static final int reqKeyboardType = 16843304; // 0x1010228
     field public static final int reqNavigation = 16843306; // 0x101022a
     field public static final int reqTouchScreen = 16843303; // 0x1010227
-    field public static final int requestLegacyExternalStorage = 16844201; // 0x10105a9
+    field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
     field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1204,7 +1198,7 @@
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
-    field public static final int secureElementName = 16844200; // 0x10105a8
+    field public static final int secureElementName = 16844290; // 0x1010602
     field public static final int seekBarStyle = 16842875; // 0x101007b
     field public static final int segmentedButtonStyle = 16843568; // 0x1010330
     field public static final int selectAllOnFocus = 16843102; // 0x101015e
@@ -1213,7 +1207,7 @@
     field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
     field @Deprecated public static final int selectedDateVerticalBar = 16843591; // 0x1010347
     field @Deprecated public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
-    field public static final int selectionDividerHeight = 16844190; // 0x101059e
+    field public static final int selectionDividerHeight = 16844184; // 0x1010598
     field public static final int sessionService = 16843837; // 0x101043d
     field public static final int settingsActivity = 16843301; // 0x1010225
     field public static final int settingsSliceUri = 16844179; // 0x1010593
@@ -1332,7 +1326,7 @@
     field public static final int supportsAssist = 16844016; // 0x10104f0
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
-    field public static final int supportsMultipleDisplays = 16844183; // 0x1010597
+    field public static final int supportsMultipleDisplays = 16844182; // 0x1010596
     field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
     field public static final int supportsRtl = 16843695; // 0x10103af
     field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
@@ -1513,9 +1507,9 @@
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
     field public static final int use32bitAbi = 16844053; // 0x1010515
-    field public static final int useAppZygote = 16844184; // 0x1010598
+    field public static final int useAppZygote = 16844183; // 0x1010597
     field public static final int useDefaultMargins = 16843641; // 0x1010379
-    field public static final int useEmbeddedDex = 16844196; // 0x10105a4
+    field public static final int useEmbeddedDex = 16844190; // 0x101059e
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -1627,7 +1621,7 @@
     field @Deprecated public static final int yearListSelectorColor = 16843930; // 0x101049a
     field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
     field public static final int zAdjustment = 16843201; // 0x10101c1
-    field public static final int zygotePreloadName = 16844195; // 0x10105a3
+    field public static final int zygotePreloadName = 16844189; // 0x101059d
   }
 
   public static final class R.bool {
@@ -34166,7 +34160,7 @@
     field public static final int O = 26; // 0x1a
     field public static final int O_MR1 = 27; // 0x1b
     field public static final int P = 28; // 0x1c
-    field public static final int Q = 10000; // 0x2710
+    field public static final int Q = 29; // 0x1d
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -56251,12 +56245,10 @@
     method public int getWindowLayoutType();
     method public boolean isAboveAnchor();
     method public boolean isAttachedInDecor();
-    method @Deprecated public boolean isClipToScreenEnabled();
     method public boolean isClippedToScreen();
     method public boolean isClippingEnabled();
     method public boolean isFocusable();
     method public boolean isLaidOutInScreen();
-    method @Deprecated public boolean isLayoutInScreenEnabled();
     method public boolean isOutsideTouchable();
     method public boolean isShowing();
     method public boolean isSplitTouchEnabled();
@@ -56265,7 +56257,6 @@
     method public void setAnimationStyle(int);
     method public void setAttachedInDecor(boolean);
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
-    method @Deprecated public void setClipToScreenEnabled(boolean);
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
     method public void setElevation(float);
@@ -56278,7 +56269,6 @@
     method public void setInputMethodMode(int);
     method public void setIsClippedToScreen(boolean);
     method public void setIsLaidOutInScreen(boolean);
-    method @Deprecated public void setLayoutInScreenEnabled(boolean);
     method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
     method public void setOutsideTouchable(boolean);
     method public void setOverlapAnchor(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index ab5e7e5..536eba1 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -691,6 +691,13 @@
     method protected <T extends android.view.View> T findViewWithTagTraversal(Object);
   }
 
+  public class PopupWindow {
+    method @Deprecated public boolean isClipToScreenEnabled();
+    method @Deprecated public boolean isLayoutInScreenEnabled();
+    method @Deprecated public void setClipToScreenEnabled(boolean);
+    method @Deprecated public void setLayoutInScreenEnabled(boolean);
+  }
+
   @android.widget.RemoteViews.RemoteView public class TextView extends android.view.View implements android.view.ViewTreeObserver.OnPreDrawListener {
     method public static int getTextColor(android.content.Context, android.content.res.TypedArray, int);
     method public static android.content.res.ColorStateList getTextColors(android.content.Context, android.content.res.TypedArray);
diff --git a/api/system-current.txt b/api/system-current.txt
index 7c66af5..97488c1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -218,7 +218,7 @@
   }
 
   public static final class R.attr {
-    field public static final int allowClearUserDataOnFailedRestore = 16844198; // 0x10105a6
+    field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
     field public static final int isVrOnly = 16844152; // 0x1010578
     field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
     field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
@@ -317,7 +317,6 @@
   public class AppOpsManager {
     method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
     method public static String[] getOpStrs();
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable int[]);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
     method public static int opToDefaultMode(@NonNull String);
@@ -936,8 +935,6 @@
     method public int restorePackage(String, android.app.backup.RestoreObserver);
     method public int restorePackages(long, @Nullable android.app.backup.RestoreObserver, @NonNull java.util.Set<java.lang.String>, @Nullable android.app.backup.BackupManagerMonitor);
     method public int restorePackages(long, @Nullable android.app.backup.RestoreObserver, @NonNull java.util.Set<java.lang.String>);
-    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor, String[]);
-    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, String[]);
   }
 
   public class RestoreSet implements android.os.Parcelable {
@@ -1092,14 +1089,11 @@
   }
 
   public static final class AppTarget.Builder {
-    ctor @Deprecated public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
     ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull String, @NonNull android.os.UserHandle);
     ctor public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId, @NonNull android.content.pm.ShortcutInfo);
     method @NonNull public android.app.prediction.AppTarget build();
     method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
     method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
   }
 
   public final class AppTargetEvent implements android.os.Parcelable {
@@ -1602,9 +1596,6 @@
     method public static void forceSafeLabels();
     method @Deprecated @NonNull public CharSequence loadSafeLabel(@NonNull android.content.pm.PackageManager);
     method @NonNull public CharSequence loadSafeLabel(@NonNull android.content.pm.PackageManager, @FloatRange(from=0) float, int);
-    field @Deprecated public static final int SAFE_LABEL_FLAG_FIRST_LINE = 4; // 0x4
-    field @Deprecated public static final int SAFE_LABEL_FLAG_SINGLE_LINE = 2; // 0x2
-    field @Deprecated public static final int SAFE_LABEL_FLAG_TRIM = 1; // 0x1
   }
 
   public abstract class PackageManager {
@@ -7102,7 +7093,6 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.WRITE_SECURE_SETTINGS}) public boolean setDefaultDialer(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
     field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
     field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 8f71122..5802f6c 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -9,6 +9,10 @@
 
 package android.app {
 
+  public class AppOpsManager {
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable int[]);
+  }
+
   public class Notification implements android.os.Parcelable {
     method public static Class<? extends android.app.Notification.Style> getNotificationStyleClass(String);
   }
@@ -28,6 +32,25 @@
 
 }
 
+package android.app.backup {
+
+  public class RestoreSession {
+    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor, String[]);
+    method @Deprecated public int restoreSome(long, android.app.backup.RestoreObserver, String[]);
+  }
+
+}
+
+package android.app.prediction {
+
+  public static final class AppTarget.Builder {
+    ctor @Deprecated public AppTarget.Builder(@NonNull android.app.prediction.AppTargetId);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+  }
+
+}
+
 package android.content {
 
   public class Intent implements java.lang.Cloneable android.os.Parcelable {
@@ -60,6 +83,16 @@
 
 }
 
+package android.content.pm {
+
+  public class PackageItemInfo {
+    field @Deprecated public static final int SAFE_LABEL_FLAG_FIRST_LINE = 4; // 0x4
+    field @Deprecated public static final int SAFE_LABEL_FLAG_SINGLE_LINE = 2; // 0x2
+    field @Deprecated public static final int SAFE_LABEL_FLAG_TRIM = 1; // 0x1
+  }
+
+}
+
 package android.hardware.hdmi {
 
   public final class HdmiControlManager {
@@ -158,6 +191,14 @@
 
 }
 
+package android.telecom {
+
+  public class TelecomManager {
+    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.WRITE_SECURE_SETTINGS}) public boolean setDefaultDialer(@Nullable String);
+  }
+
+}
+
 package android.telephony {
 
   public class TelephonyManager {
diff --git a/api/test-current.txt b/api/test-current.txt
index 181932c..0de0d75 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -520,8 +520,6 @@
     method @NonNull public android.app.prediction.AppTarget build();
     method @NonNull public android.app.prediction.AppTarget.Builder setClassName(@NonNull String);
     method @NonNull public android.app.prediction.AppTarget.Builder setRank(@IntRange(from=0) int);
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
   }
 
   public final class AppTargetEvent implements android.os.Parcelable {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 83a5708..ef0aac7 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -1,4 +1,13 @@
 // Signature format: 2.0
+package android.app.prediction {
+
+  public static final class AppTarget.Builder {
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull String, @NonNull android.os.UserHandle);
+    method @Deprecated @NonNull public android.app.prediction.AppTarget.Builder setTarget(@NonNull android.content.pm.ShortcutInfo);
+  }
+
+}
+
 package android.provider {
 
   public final class DeviceConfig {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index ec02b12..4e0a8eb 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -611,11 +611,8 @@
 
 void StatsLogProcessor::SaveActiveConfigsToDisk(int64_t currentTimeNs) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-
     const int64_t timeNs = getElapsedRealtimeNs();
     // Do not write to disk if we already have in the last few seconds.
-    // This is to avoid overwriting files that would have the same name if we
-    //   write twice in the same second.
     if (static_cast<unsigned long long> (timeNs) <
             mLastActiveMetricsWriteNs + WRITE_DATA_COOL_DOWN_SEC * NS_PER_SEC) {
         ALOGI("Statsd skipping writing active metrics to disk. Already wrote data in last %d seconds",
@@ -625,13 +622,7 @@
     mLastActiveMetricsWriteNs = timeNs;
 
     ProtoOutputStream proto;
-    for (const auto& pair : mMetricsManagers) {
-        const sp<MetricsManager>& metricsManager = pair.second;
-        uint64_t configToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
-                                                     FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG);
-        metricsManager->writeActiveConfigToProtoOutputStream(currentTimeNs, &proto);
-        proto.end(configToken);
-    }
+    WriteActiveConfigsToProtoOutputStreamLocked(currentTimeNs, DEVICE_SHUTDOWN, &proto);
 
     string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR);
     StorageManager::deleteFile(file_name.c_str());
@@ -644,9 +635,24 @@
     proto.flush(fd.get());
 }
 
+void StatsLogProcessor::WriteActiveConfigsToProtoOutputStream(
+        int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto) {
+    std::lock_guard<std::mutex> lock(mMetricsMutex);
+    WriteActiveConfigsToProtoOutputStreamLocked(currentTimeNs, reason, proto);
+}
+
+void StatsLogProcessor::WriteActiveConfigsToProtoOutputStreamLocked(
+        int64_t currentTimeNs,  const DumpReportReason reason, ProtoOutputStream* proto) {
+    for (const auto& pair : mMetricsManagers) {
+        const sp<MetricsManager>& metricsManager = pair.second;
+        uint64_t configToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                                     FIELD_ID_ACTIVE_CONFIG_LIST_CONFIG);
+        metricsManager->writeActiveConfigToProtoOutputStream(currentTimeNs, reason, proto);
+        proto->end(configToken);
+    }
+}
 void StatsLogProcessor::LoadActiveConfigsFromDisk() {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-
     string file_name = StringPrintf("%s/active_metrics", STATS_ACTIVE_METRIC_DIR);
     int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
     if (-1 == fd) {
@@ -670,6 +676,19 @@
         StorageManager::deleteFile(file_name.c_str());
         return;
     }
+    // Passing in mTimeBaseNs only works as long as we only load from disk is when statsd starts.
+    SetConfigsActiveStateLocked(activeConfigList, mTimeBaseNs);
+    StorageManager::deleteFile(file_name.c_str());
+}
+
+void StatsLogProcessor::SetConfigsActiveState(const ActiveConfigList& activeConfigList,
+                                                    int64_t currentTimeNs) {
+    std::lock_guard<std::mutex> lock(mMetricsMutex);
+    SetConfigsActiveStateLocked(activeConfigList, currentTimeNs);
+}
+
+void StatsLogProcessor::SetConfigsActiveStateLocked(const ActiveConfigList& activeConfigList,
+                                                    int64_t currentTimeNs) {
     for (int i = 0; i < activeConfigList.config_size(); i++) {
         const auto& config = activeConfigList.config(i);
         ConfigKey key(config.uid(), config.id());
@@ -679,11 +698,9 @@
             continue;
         }
         VLOG("Setting active config %s", key.ToString().c_str());
-        it->second->loadActiveConfig(config, mTimeBaseNs);
+        it->second->loadActiveConfig(config, currentTimeNs);
     }
     VLOG("Successfully loaded %d active configs.", activeConfigList.config_size());
-
-    StorageManager::deleteFile(file_name.c_str());
 }
 
 void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 0dc597b..92aa425 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -31,17 +31,6 @@
 namespace os {
 namespace statsd {
 
-// Keep this in sync with DumpReportReason enum in stats_log.proto
-enum DumpReportReason {
-    DEVICE_SHUTDOWN = 1,
-    CONFIG_UPDATED = 2,
-    CONFIG_REMOVED = 3,
-    GET_DATA_CALLED = 4,
-    ADB_DUMP = 5,
-    CONFIG_RESET = 6,
-    STATSCOMPANION_DIED = 7,
-    TERMINATION_SIGNAL_RECEIVED = 8
-};
 
 class StatsLogProcessor : public ConfigListener {
 public:
@@ -92,9 +81,16 @@
     /* Persist configs containing metrics with active activations to disk. */
     void SaveActiveConfigsToDisk(int64_t currentTimeNs);
 
+    /* Writes the current active status/ttl for all configs and metrics to ProtoOutputStream. */
+    void WriteActiveConfigsToProtoOutputStream(
+            int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
+
     /* Load configs containing metrics with active activations from disk. */
     void LoadActiveConfigsFromDisk();
 
+    /* Sets the active status/ttl for all configs and metrics to the status in ActiveConfigList. */
+    void SetConfigsActiveState(const ActiveConfigList& activeConfigList, int64_t currentTimeNs);
+
     // Reset all configs.
     void resetConfigs();
 
@@ -158,6 +154,12 @@
 
     void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
 
+    void WriteActiveConfigsToProtoOutputStreamLocked(
+            int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
+
+    void SetConfigsActiveStateLocked(const ActiveConfigList& activeConfigList,
+                                     int64_t currentTimeNs);
+
     void WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
                                const DumpLatency dumpLatency);
     void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs,
@@ -224,6 +226,7 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
     FRIEND_TEST(StatsLogProcessorTest,
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
 
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 623a1f2..8191d37 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1478,8 +1478,21 @@
     StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
     if (mProcessor != nullptr) {
         ALOGW("Reset statsd upon system server restarts.");
+        int64_t systemServerRestartNs = getElapsedRealtimeNs();
+        ProtoOutputStream proto;
+        mProcessor->WriteActiveConfigsToProtoOutputStream(systemServerRestartNs,
+                STATSCOMPANION_DIED, &proto);
+
         mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST);
         mProcessor->resetConfigs();
+
+        std::string serializedActiveConfigs;
+        if (proto.serializeToString(&serializedActiveConfigs)) {
+            ActiveConfigList activeConfigs;
+            if (activeConfigs.ParseFromString(serializedActiveConfigs)) {
+                mProcessor->SetConfigsActiveState(activeConfigs, systemServerRestartNs);
+            }
+        }
     }
     mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
     mPeriodicAlarmMonitor->setStatsCompanionService(nullptr);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 936f7db..a4e6d7f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -427,6 +427,7 @@
 
     std::shared_ptr<LogEventQueue> mEventQueue;
 
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
     FRIEND_TEST(StatsServiceTest, TestAddConfig_simple);
     FRIEND_TEST(StatsServiceTest, TestAddConfig_empty);
     FRIEND_TEST(StatsServiceTest, TestAddConfig_invalid);
diff --git a/cmds/statsd/src/active_config_list.proto b/cmds/statsd/src/active_config_list.proto
index ef8e50b..9929833 100644
--- a/cmds/statsd/src/active_config_list.proto
+++ b/cmds/statsd/src/active_config_list.proto
@@ -26,7 +26,18 @@
 
     // Time left in activation. When this proto is loaded after device boot,
     // the activation should be set to active for this duration.
+    // This field will only be set when the state is ACTIVE
     optional int64 remaining_ttl_nanos = 2;
+
+    enum State {
+        UNNKNOWN = 0;
+        // This metric should activate for remaining_ttl_nanos when we load the activations.
+        ACTIVE = 1;
+        // When we load the activations, this metric should activate on next boot for the tll
+        // specified in the config.
+        ACTIVATE_ON_BOOT = 2;
+    }
+    optional State state = 3;
 }
 
 message ActiveMetric {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f53ac1b..d69eced 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -299,6 +299,10 @@
         CarPowerStateChanged car_power_state_changed = 203;
         GarageModeInfo garage_mode_info = 204;
         TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
+        ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
+        ContentCaptureServiceEvents content_capture_service_events = 207;
+        ContentCaptureSessionEvents content_capture_session_events = 208;
+        ContentCaptureFlushed content_capture_flushed = 209;
     }
 
     // Pulled events will start at field 10000.
@@ -364,6 +368,7 @@
         AppsOnExternalStorageInfo apps_on_external_storage_info = 10057;
         FaceSettings face_settings = 10058;
         CoolingDevice cooling_device = 10059;
+        AppOps app_ops = 10060;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -4830,6 +4835,95 @@
 }
 
 /**
+ * Logs information about mismatched caller for content capture.
+ *
+ * Logged from:
+ *   frameworks/base/core/java/android/service/contentcapture/ContentCaptureService.java
+ */
+message ContentCaptureCallerMismatchReported {
+    optional string intended_package = 1;
+    optional string calling_package = 2;
+}
+
+/**
+ * Logs information about content capture service events.
+ *
+ * Logged from:
+ *   frameworks/base/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java
+ */
+message ContentCaptureServiceEvents {
+    // The type of event.
+    enum Event {
+        UNKNOWN = 0;
+        ON_CONNECTED = 1;
+        ON_DISCONNECTED = 2;
+        SET_WHITELIST = 3;
+        SET_DISABLED = 4;
+        ON_USER_DATA_REMOVED = 5;
+    }
+    optional Event event = 1;
+    // component/package of content capture service.
+    optional string service_info = 2;
+    // component/package of target.
+    // it's a concatenated list of component/package for SET_WHITELIST event
+    // separated by " ".
+    optional string target_info = 3;
+}
+
+/**
+ * Logs information about content capture session events.
+ *
+ * Logged from:
+ *   frameworks/base/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java
+ */
+message ContentCaptureSessionEvents {
+    // The type of event.
+    enum Event {
+        UNKNOWN = 0;
+        ON_SESSION_STARTED = 1;
+        ON_SESSION_FINISHED = 2;
+        SESSION_NOT_CREATED = 3;
+    }
+    optional int32 session_id = 1;
+    optional Event event = 2;
+    // (n/a on session finished)
+    optional int32 state_flags = 3;
+    // component/package of content capture service.
+    optional string service_info = 4;
+    // component/package of app.
+    // (n/a on session finished)
+    optional string app_info = 5;
+    optional bool is_child_session = 6;
+}
+
+/**
+ * Logs information about session being flushed.
+ *
+ * Logged from:
+ *   frameworks/base/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java
+ */
+message ContentCaptureFlushed {
+    optional int32 session_id = 1;
+    // component/package of content capture service.
+    optional string service_info = 2;
+    // component/package of app.
+    optional string app_info = 3;
+    // session start/finish events
+    optional int32 child_session_started = 4;
+    optional int32 child_session_finished = 5;
+    // count of view events.
+    optional int32 view_appeared_count = 6;
+    optional int32 view_disappeared_count = 7;
+    optional int32 view_text_changed_count = 8;
+
+    // Flush stats.
+    optional int32 max_events = 9;
+    optional int32 idle_flush_freq = 10;
+    optional int32 text_flush_freq = 11;
+    optional int32 flush_reason = 12;
+}
+
+/**
  * Pulls on-device BatteryStats power use calculations for the overall device.
  */
 message DeviceCalculatedPowerUse {
@@ -6357,3 +6451,41 @@
     // Whether GarageMode is entered.
     optional bool is_garage_mode = 1;
 }
+
+/**
+ * Historical app ops data per package.
+ */
+message AppOps {
+    // Uid of the package requesting the op
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // Nmae of the package performing the op
+    optional string package_name = 2;
+
+    // operation id; maps to the OP_* constants in AppOpsManager.java
+    optional int32 op_id = 3;
+
+    // The number of times the op was granted while the app was in the
+    // foreground (only for trusted requests)
+    optional int64 trusted_foreground_granted_count = 4;
+
+    // The number of times the op was granted while the app was in the
+    // background (only for trusted requests)
+    optional int64 trusted_background_granted_count = 5;
+
+    // The number of times the op was rejected while the app was in the
+    // foreground (only for trusted requests)
+    optional int64 trusted_foreground_rejected_count = 6;
+
+    // The number of times the op was rejected while the app was in the
+    // background (only for trusted requests)
+    optional int64 trusted_background_rejected_count = 7;
+
+    // For long-running operations, total duration of the operation
+    // while the app was in the foreground (only for trusted requests)
+    optional int64 trusted_foreground_duration_millis = 8;
+
+    // For long-running operations, total duration of the operation
+    // while the app was in the background (only for trusted requests)
+    optional int64 trusted_background_duration_millis = 9;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 2ffe18e..914d60d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -260,6 +260,9 @@
         // Face Settings
         {android::util::FACE_SETTINGS,
          {.puller = new StatsCompanionServicePuller(android::util::FACE_SETTINGS)}},
+        // App ops
+        {android::util::APP_OPS,
+         {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 9ad7f09..d913427 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -19,6 +19,7 @@
 #include "MetricProducer.h"
 
 using android::util::FIELD_COUNT_REPEATED;
+using android::util::FIELD_TYPE_ENUM;
 using android::util::FIELD_TYPE_INT32;
 using android::util::FIELD_TYPE_INT64;
 using android::util::FIELD_TYPE_MESSAGE;
@@ -37,6 +38,7 @@
 // for ActiveEventActivation
 const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX = 1;
 const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2;
+const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3;
 
 void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
     if (!mIsActive) {
@@ -165,17 +167,21 @@
             continue;
         }
         auto& activation = it->second;
-        // We don't want to change the ttl for future activations, so we set the start_ns
-        // such that start_ns + ttl_ns == currentTimeNs + remaining_ttl_nanos
-        activation->start_ns =
-            currentTimeNs + activeEventActivation.remaining_ttl_nanos() - activation->ttl_ns;
-        activation->state = ActivationState::kActive;
-        mIsActive = true;
+        if (activeEventActivation.state() == ActiveEventActivation::ACTIVE) {
+            // We don't want to change the ttl for future activations, so we set the start_ns
+            // such that start_ns + ttl_ns == currentTimeNs + remaining_ttl_nanos
+            activation->start_ns =
+                currentTimeNs + activeEventActivation.remaining_ttl_nanos() - activation->ttl_ns;
+            activation->state = ActivationState::kActive;
+            mIsActive = true;
+        } else if (activeEventActivation.state() == ActiveEventActivation::ACTIVATE_ON_BOOT) {
+            activation->state = ActivationState::kActiveOnBoot;
+        }
     }
 }
 
 void MetricProducer::writeActiveMetricToProtoOutputStream(
-        int64_t currentTimeNs, ProtoOutputStream* proto) {
+        int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto) {
     proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_METRIC_ID, (long long)mMetricId);
     for (auto& it : mEventActivationMap) {
         const int atom_matcher_index = it.first;
@@ -196,9 +202,22 @@
                     activation->start_ns + activation->ttl_ns - currentTimeNs;
             proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS,
                     (long long)remainingTtlNs);
+            proto->write(FIELD_TYPE_ENUM | FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE,
+                    ActiveEventActivation::ACTIVE);
+
         } else if (ActivationState::kActiveOnBoot == activation->state) {
-            proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS,
-                    (long long)activation->ttl_ns);
+            if (reason == DEVICE_SHUTDOWN || reason == TERMINATION_SIGNAL_RECEIVED) {
+                proto->write(
+                        FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS,
+                        (long long)activation->ttl_ns);
+                proto->write(FIELD_TYPE_ENUM | FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE,
+                                    ActiveEventActivation::ACTIVE);
+            } else if (reason == STATSCOMPANION_DIED) {
+                // We are saving because of system server death, not due to a device shutdown.
+                // Next time we load, we do not want to activate metrics that activate on boot.
+                proto->write(FIELD_TYPE_ENUM | FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE,
+                                                    ActiveEventActivation::ACTIVATE_ON_BOOT);
+            }
         }
         proto->end(activationToken);
     }
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index ec3484c..3ddbef4 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -35,6 +35,18 @@
 namespace os {
 namespace statsd {
 
+// Keep this in sync with DumpReportReason enum in stats_log.proto
+enum DumpReportReason {
+    DEVICE_SHUTDOWN = 1,
+    CONFIG_UPDATED = 2,
+    CONFIG_REMOVED = 3,
+    GET_DATA_CALLED = 4,
+    ADB_DUMP = 5,
+    CONFIG_RESET = 6,
+    STATSCOMPANION_DIED = 7,
+    TERMINATION_SIGNAL_RECEIVED = 8
+};
+
 // If the metric has no activation requirement, it will be active once the metric producer is
 // created.
 // If the metric needs to be activated by atoms, the metric producer will start
@@ -244,7 +256,7 @@
     void flushIfExpire(int64_t elapsedTimestampNs);
 
     void writeActiveMetricToProtoOutputStream(
-            int64_t currentTimeNs, ProtoOutputStream* proto);
+            int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
 protected:
     virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
     virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
@@ -268,8 +280,6 @@
         return mIsActive;
     }
 
-    void prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs);
-
     void loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs);
 
     virtual void prepareFirstBucketLocked() {};
@@ -412,6 +422,7 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
     FRIEND_TEST(StatsLogProcessorTest,
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 947f377..207a7dd 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -528,14 +528,14 @@
 }
 
 void MetricsManager::writeActiveConfigToProtoOutputStream(
-        int64_t currentTimeNs, ProtoOutputStream* proto) {
+        int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto) {
     proto->write(FIELD_TYPE_INT64 | FIELD_ID_ACTIVE_CONFIG_ID, (long long)mConfigKey.GetId());
     proto->write(FIELD_TYPE_INT32 | FIELD_ID_ACTIVE_CONFIG_UID, mConfigKey.GetUid());
     for (int metricIndex : mMetricIndexesWithActivation) {
         const auto& metric = mAllMetricProducers[metricIndex];
         const uint64_t metricToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                 FIELD_ID_ACTIVE_CONFIG_METRIC);
-        metric->writeActiveMetricToProtoOutputStream(currentTimeNs, proto);
+        metric->writeActiveMetricToProtoOutputStream(currentTimeNs, reason, proto);
         proto->end(metricToken);
     }
 }
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 818131e..da3be06 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -141,7 +141,7 @@
     void loadActiveConfig(const ActiveConfig& config, int64_t currentTimeNs);
 
     void writeActiveConfigToProtoOutputStream(
-            int64_t currentTimeNs, ProtoOutputStream* proto);
+            int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
 
 private:
     // For test only.
@@ -290,6 +290,7 @@
     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
     FRIEND_TEST(StatsLogProcessorTest,
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 4e419b6..a2fd9d4 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -330,6 +330,8 @@
 
   // Class name of the incident report receiver.
   optional string receiver_cls = 4;
+
+  optional string alert_description = 5;
 }
 
 message PerfettoDetails {
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index ff1cb4f..f2c6f1a 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -36,12 +36,14 @@
 using android::util::ProtoOutputStream;
 using std::vector;
 
-using util::FIELD_TYPE_MESSAGE;
 using util::FIELD_TYPE_INT32;
 using util::FIELD_TYPE_INT64;
+using util::FIELD_TYPE_MESSAGE;
+using util::FIELD_TYPE_STRING;
 
 // field ids in IncidentHeaderProto
 const int FIELD_ID_ALERT_ID = 1;
+const int FIELD_ID_REASON = 2;
 const int FIELD_ID_CONFIG_KEY = 3;
 const int FIELD_ID_CONFIG_KEY_UID = 1;
 const int FIELD_ID_CONFIG_KEY_ID = 2;
@@ -57,9 +59,11 @@
 
 namespace {
 void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensionKey& dimensionKey,
-                  int64_t metricValue, const ConfigKey& configKey, vector<uint8_t>* protoData) {
+                  int64_t metricValue, const ConfigKey& configKey, const string& reason,
+                  vector<uint8_t>* protoData) {
     ProtoOutputStream headerProto;
     headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
+    headerProto.write(FIELD_TYPE_STRING | FIELD_ID_REASON, reason);
     uint64_t token =
             headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
     headerProto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_KEY_UID, configKey.GetUid());
@@ -142,7 +146,8 @@
     IncidentReportArgs incidentReport;
 
     vector<uint8_t> protoData;
-    getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey, &protoData);
+    getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey,
+                 config.alert_description(), &protoData);
     incidentReport.addHeader(protoData);
 
     for (int i = 0; i < config.section_size(); i++) {
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 49b4e90..fe25a25 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -13,12 +13,14 @@
 // limitations under the License.
 
 #include "StatsLogProcessor.h"
+#include "StatsService.h"
 #include "config/ConfigKey.h"
 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "guardrail/StatsdStats.h"
 #include "logd/LogEvent.h"
 #include "packages/UidMap.h"
+#include "storage/StorageManager.h"
 #include "statslog.h"
 
 #include <gmock/gmock.h>
@@ -97,7 +99,8 @@
     ConfigKey key(100, 12345);
     EXPECT_CALL(mockMetricsManager, byteSize())
             .Times(1)
-            .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
+            .WillRepeatedly(::testing::Return(int(
+                    StatsdStats::kMaxMetricsBytesPerConfig * .95)));
 
     // Expect only one broadcast despite always returning a size that should trigger broadcast.
     p.flushIfNecessaryLocked(1, key, mockMetricsManager);
@@ -128,7 +131,7 @@
     ConfigKey key(100, 12345);
     EXPECT_CALL(mockMetricsManager, byteSize())
             .Times(1)
-            .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
+            .WillRepeatedly(::testing::Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
 
     EXPECT_CALL(mockMetricsManager, dropData(_)).Times(1);
 
@@ -1482,6 +1485,236 @@
     // }}}---------------------------------------------------------------------------
 }
 
+TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
+    int uid = 9876;
+    long configId = 12341;
+
+    // Create config with 3 metrics:
+    // Metric 1: Activate on 2 activations, 1 on boot, 1 immediate.
+    // Metric 2: Activate on 2 activations, 1 on boot, 1 immediate.
+    // Metric 3: Always active
+    StatsdConfig config1;
+    config1.set_id(configId);
+    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+    auto jobStartMatcher = CreateStartScheduledJobAtomMatcher();
+    auto jobFinishMatcher = CreateFinishScheduledJobAtomMatcher();
+    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+    *config1.add_atom_matcher() = screenOnMatcher;
+    *config1.add_atom_matcher() = jobStartMatcher;
+    *config1.add_atom_matcher() = jobFinishMatcher;
+
+    long metricId1 = 1234561;
+    long metricId2 = 1234562;
+    long metricId3 = 1234563;
+
+    auto countMetric1 = config1.add_count_metric();
+    countMetric1->set_id(metricId1);
+    countMetric1->set_what(wakelockAcquireMatcher.id());
+    countMetric1->set_bucket(FIVE_MINUTES);
+
+    auto countMetric2 = config1.add_count_metric();
+    countMetric2->set_id(metricId2);
+    countMetric2->set_what(wakelockAcquireMatcher.id());
+    countMetric2->set_bucket(FIVE_MINUTES);
+
+    auto countMetric3 = config1.add_count_metric();
+    countMetric3->set_id(metricId3);
+    countMetric3->set_what(wakelockAcquireMatcher.id());
+    countMetric3->set_bucket(FIVE_MINUTES);
+
+    // Metric 1 activates on boot for wakelock acquire, immediately for screen on.
+    auto metric1Activation = config1.add_metric_activation();
+    metric1Activation->set_metric_id(metricId1);
+    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+    metric1ActivationTrigger1->set_ttl_seconds(100);
+    metric1ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+    metric1ActivationTrigger2->set_ttl_seconds(200);
+    metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+
+    // Metric 2 activates on boot for scheduled job start, immediately for scheduled job finish.
+    auto metric2Activation = config1.add_metric_activation();
+    metric2Activation->set_metric_id(metricId2);
+    auto metric2ActivationTrigger1 = metric2Activation->add_event_activation();
+    metric2ActivationTrigger1->set_atom_matcher_id(jobStartMatcher.id());
+    metric2ActivationTrigger1->set_ttl_seconds(100);
+    metric2ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+    auto metric2ActivationTrigger2 = metric2Activation->add_event_activation();
+    metric2ActivationTrigger2->set_atom_matcher_id(jobFinishMatcher.id());
+    metric2ActivationTrigger2->set_ttl_seconds(200);
+    metric2ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+
+    // Send the config.
+    StatsService service(nullptr, nullptr);
+    string serialized = config1.SerializeAsString();
+    service.addConfigurationChecked(uid, configId, {serialized.begin(), serialized.end()});
+
+    // Make sure the config is stored on disk. Otherwise, we will not reset on system server death.
+    StatsdConfig tmpConfig;
+    ConfigKey cfgKey1(uid, configId);
+    EXPECT_TRUE(StorageManager::readConfigFromDisk(cfgKey1, &tmpConfig));
+
+    // Metric 1 is not active.
+    // Metric 2 is not active.
+    // Metric 3 is active.
+    // {{{---------------------------------------------------------------------------
+    sp<StatsLogProcessor> processor = service.mProcessor;
+    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    auto it = processor->mMetricsManagers.find(cfgKey1);
+    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+    auto& metricsManager1 = it->second;
+    EXPECT_TRUE(metricsManager1->isActive());
+    EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
+
+    auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
+    EXPECT_EQ(metricId1, metricProducer1->getMetricId());
+    EXPECT_FALSE(metricProducer1->isActive());
+
+    auto& metricProducer2 = metricsManager1->mAllMetricProducers[1];
+    EXPECT_EQ(metricId2, metricProducer2->getMetricId());
+    EXPECT_FALSE(metricProducer2->isActive());
+
+    auto& metricProducer3 = metricsManager1->mAllMetricProducers[2];
+    EXPECT_EQ(metricId3, metricProducer3->getMetricId());
+    EXPECT_TRUE(metricProducer3->isActive());
+
+    // Check event activations.
+    EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
+    EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
+              metric1ActivationTrigger1->atom_matcher_id());
+    const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+    EXPECT_EQ(0, activation1->start_ns);
+    EXPECT_EQ(kNotActive, activation1->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
+
+    EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
+              metric1ActivationTrigger2->atom_matcher_id());
+    const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
+    EXPECT_EQ(0, activation2->start_ns);
+    EXPECT_EQ(kNotActive, activation2->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
+
+    EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
+              metric2ActivationTrigger1->atom_matcher_id());
+    const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
+    EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
+    EXPECT_EQ(0, activation3->start_ns);
+    EXPECT_EQ(kNotActive, activation3->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
+
+    EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
+              metric2ActivationTrigger2->atom_matcher_id());
+    const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
+    EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
+    EXPECT_EQ(0, activation4->start_ns);
+    EXPECT_EQ(kNotActive, activation4->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation4->activationType);
+    // }}}------------------------------------------------------------------------------
+
+    // Trigger Activation 1 for Metric 1. Should activate on boot.
+    // Trigger Activation 4 for Metric 2. Should activate immediately.
+    long configAddedTimeNs = metricsManager1->mLastReportTimeNs;
+    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 1 + configAddedTimeNs);
+    processor->OnLogEvent(event.get());
+
+    event = CreateFinishScheduledJobEvent(attributions1, "finish1", 2 + configAddedTimeNs);
+    processor->OnLogEvent(event.get());
+
+    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+    // Metric 2 is active. Activation 4 set to kActive
+    // Metric 3 is active.
+    // {{{---------------------------------------------------------------------------
+    EXPECT_FALSE(metricProducer1->isActive());
+    EXPECT_EQ(0, activation1->start_ns);
+    EXPECT_EQ(kActiveOnBoot, activation1->state);
+    EXPECT_EQ(0, activation2->start_ns);
+    EXPECT_EQ(kNotActive, activation2->state);
+
+    EXPECT_TRUE(metricProducer2->isActive());
+    EXPECT_EQ(0, activation3->start_ns);
+    EXPECT_EQ(kNotActive, activation3->state);
+    EXPECT_EQ(2 + configAddedTimeNs, activation4->start_ns);
+    EXPECT_EQ(kActive, activation4->state);
+
+    EXPECT_TRUE(metricProducer3->isActive());
+    // }}}-----------------------------------------------------------------------------
+
+    // Can't fake time with StatsService.
+    // Lets get a time close to the system server death time and make sure it's sane.
+    int64_t approximateSystemServerDeath = getElapsedRealtimeNs();
+    EXPECT_TRUE(approximateSystemServerDeath > 2 + configAddedTimeNs);
+    EXPECT_TRUE(approximateSystemServerDeath < NS_PER_SEC + configAddedTimeNs);
+
+    // System server dies.
+    service.binderDied(nullptr);
+
+    // We should have a new metrics manager. Lets get it and ensure activation status is restored.
+    // {{{---------------------------------------------------------------------------
+    EXPECT_EQ(1, processor->mMetricsManagers.size());
+    it = processor->mMetricsManagers.find(cfgKey1);
+    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+    auto& metricsManager2 = it->second;
+    EXPECT_TRUE(metricsManager2->isActive());
+    EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
+
+    auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
+    EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
+    EXPECT_FALSE(metricProducer1001->isActive());
+
+    auto& metricProducer1002 = metricsManager2->mAllMetricProducers[1];
+    EXPECT_EQ(metricId2, metricProducer1002->getMetricId());
+    EXPECT_TRUE(metricProducer1002->isActive());
+
+    auto& metricProducer1003 = metricsManager2->mAllMetricProducers[2];
+    EXPECT_EQ(metricId3, metricProducer1003->getMetricId());
+    EXPECT_TRUE(metricProducer1003->isActive());
+
+    // Check event activations.
+    // Activation 1 is kActiveOnBoot.
+    // Activation 2 and 3 are not active.
+    // Activation 4 is active.
+    EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
+    EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
+              metric1ActivationTrigger1->atom_matcher_id());
+    const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
+    EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
+    EXPECT_EQ(0, activation1001->start_ns);
+    EXPECT_EQ(kActiveOnBoot, activation1001->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
+
+    EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
+              metric1ActivationTrigger2->atom_matcher_id());
+    const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
+    EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
+    EXPECT_EQ(0, activation1002->start_ns);
+    EXPECT_EQ(kNotActive, activation1002->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
+
+    EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
+              metric2ActivationTrigger1->atom_matcher_id());
+    const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
+    EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
+    EXPECT_EQ(0, activation1003->start_ns);
+    EXPECT_EQ(kNotActive, activation1003->state);
+    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
+
+    EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
+              metric2ActivationTrigger2->atom_matcher_id());
+    const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
+    EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
+    EXPECT_EQ(2 + configAddedTimeNs, activation1004->start_ns);
+    EXPECT_EQ(kActive, activation1004->state);
+    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1004->activationType);
+    // }}}------------------------------------------------------------------------------
+}
+
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f8d7b51..45c7168 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -4370,6 +4370,7 @@
      * {@link #getOpsForPackage(int, String, String...)})}.
      *
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 19f4335..9727621 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -636,6 +636,11 @@
         public int hashCode() {
             return Objects.hash(mEvent, mId);
         }
+
+        /** @hide */
+        public boolean eventEquals(SecurityEvent other) {
+            return other != null && mEvent.equals(other.mEvent);
+        }
     }
     /**
      * Retrieve all security logs and return immediately.
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 084b13b..9336704 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -214,6 +214,7 @@
      *
      * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver,
      *   BackupManagerMonitor, Set)} instead.
+     * @removed
      */
     @Deprecated
     public int restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor,
@@ -240,6 +241,7 @@
      *
      * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver, Set)}
      *   instead.
+     * @removed
      */
     @Deprecated
     public int restoreSome(long token, RestoreObserver observer, String[] packages) {
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 61e4569..147c500 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -206,6 +206,7 @@
         /**
          * @deprecated Use the other Builder constructors.
          * @hide
+         * @removed
          */
         @Deprecated
         @SystemApi
@@ -244,6 +245,7 @@
 
         /**
          * @deprecated Use the appropriate constructor.
+         * @removed
          */
         @NonNull
         @Deprecated
@@ -258,6 +260,7 @@
 
         /**
          * @deprecated Use the appropriate constructor.
+         * @removed
          */
         @NonNull
         @Deprecated
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 7fa4360..749a011 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -281,20 +281,13 @@
 
     /**
      * Gets application usage stats for the given time range, aggregated by the specified interval.
-     * <p>The returned list will contain a {@link UsageStats} object for each package that
-     * has data for an interval that is a subset of the time range given. To illustrate:</p>
-     * <pre>
-     * intervalType = INTERVAL_YEARLY
-     * beginTime = 2013
-     * endTime = 2015 (exclusive)
      *
-     * Results:
-     * 2013 - com.example.alpha
-     * 2013 - com.example.beta
-     * 2014 - com.example.alpha
-     * 2014 - com.example.beta
-     * 2014 - com.example.charlie
-     * </pre>
+     * <p>
+     * The returned list will contain one or more {@link UsageStats} objects for each package, with
+     * usage data that covers at least the given time range.
+     * Note: The begin and end times of the time range may be expanded to the nearest whole interval
+     * period.
+     * </p>
      *
      * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
      *
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 71242fb..7cdd268 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -820,6 +820,7 @@
     private String setCallingPackage(String callingPackage) {
         final String original = mCallingPackage.get();
         mCallingPackage.set(callingPackage);
+        onCallingPackageChanged();
         return original;
     }
 
@@ -845,6 +846,15 @@
         return pkg;
     }
 
+    /** {@hide} */
+    public final @Nullable String getCallingPackageUnchecked() {
+        return mCallingPackage.get();
+    }
+
+    /** {@hide} */
+    public void onCallingPackageChanged() {
+    }
+
     /**
      * Opaque token representing the identity of an incoming IPC.
      */
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index ff7b347..081c5ad 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -62,6 +62,7 @@
      *
      * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_TRIM} instead
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
@@ -75,6 +76,7 @@
      *
      * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_SINGLE_LINE} instead
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
@@ -88,6 +90,7 @@
      *
      * @deprecated Use {@link TextUtils#SAFE_STRING_FLAG_FIRST_LINE} instead
      * @hide
+     * @removed
      */
     @Deprecated
     @SystemApi
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index b0142ea..f662b61 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -98,7 +98,7 @@
      * identifiers, while removable cameras have a unique identifier for each
      * individual device, even if they are the same model.</p>
      *
-     * <p>This list doesn't contain physical cameras that can only used as part of a logical
+     * <p>This list doesn't contain physical cameras that can only be used as part of a logical
      * multi-camera device.</p>
      *
      * @return The list of currently connected camera devices.
@@ -263,7 +263,7 @@
      * immutable for a given camera.</p>
      *
      * <p>From API level 29, this function can also be used to query the capabilities of physical
-     * cameras that can only be used as part of logical multi-camera. These cameras cannot not be
+     * cameras that can only be used as part of logical multi-camera. These cameras cannot be
      * opened directly via {@link #openCamera}</p>
      *
      * @param cameraId The id of the camera device to query. This could be either a standalone
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 3a4741a..1c97407 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -976,8 +976,7 @@
          * to come. Con permiso, Capitan. The hall is rented, the orchestra
          * engaged. It's now time to see if you can dance.</em>
          */
-        public static final int Q = CUR_DEVELOPMENT;
-
+        public static final int Q = 29;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index ed8d3f7..a94fd65 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,6 +35,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Class to take an incident report.
@@ -248,6 +250,24 @@
         public @NonNull String toString() {
             return "PendingReport(" + getUri().toString() + ")";
         }
+
+        /**
+         * @inheritDoc
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (!(obj instanceof PendingReport)) {
+                return false;
+            }
+            final PendingReport that = (PendingReport) obj;
+            return this.mUri.equals(that.mUri)
+                    && this.mFlags == that.mFlags
+                    && this.mRequestingPackage.equals(that.mRequestingPackage)
+                    && this.mTimestamp == that.mTimestamp;
+        }
     }
 
     /**
@@ -355,21 +375,35 @@
     }
 
     /**
-     * Listener for the status of an incident report being authroized or denied.
+     * Listener for the status of an incident report being authorized or denied.
      *
      * @see #requestAuthorization
      * @see #cancelAuthorization
      */
     public static class AuthListener {
+        Executor mExecutor;
+
         IIncidentAuthListener.Stub mBinder = new IIncidentAuthListener.Stub() {
             @Override
             public void onReportApproved() {
-                AuthListener.this.onReportApproved();
+                if (mExecutor != null) {
+                    mExecutor.execute(() -> {
+                        AuthListener.this.onReportApproved();
+                    });
+                } else {
+                    AuthListener.this.onReportApproved();
+                }
             }
 
             @Override
             public void onReportDenied() {
-                AuthListener.this.onReportDenied();
+                if (mExecutor != null) {
+                    mExecutor.execute(() -> {
+                        AuthListener.this.onReportDenied();
+                    });
+                } else {
+                    AuthListener.this.onReportDenied();
+                }
             }
         };
 
@@ -410,7 +444,23 @@
     @RequiresPermission(android.Manifest.permission.REQUEST_INCIDENT_REPORT_APPROVAL)
     public void requestAuthorization(int callingUid, String callingPackage, int flags,
             AuthListener listener) {
+        requestAuthorization(callingUid, callingPackage, flags,
+                mContext.getMainExecutor(), listener);
+    }
+
+    /**
+     * Request authorization of an incident report.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.REQUEST_INCIDENT_REPORT_APPROVAL)
+    public void requestAuthorization(int callingUid, @NonNull String callingPackage, int flags,
+             @NonNull @CallbackExecutor Executor executor, @NonNull AuthListener listener) {
         try {
+            if (listener.mExecutor != null) {
+                throw new RuntimeException("Do not reuse AuthListener objects when calling"
+                        + " requestAuthorization");
+            }
+            listener.mExecutor = executor;
             getCompanionServiceLocked().authorizeReport(callingUid, callingPackage, null, null,
                     flags, listener.mBinder);
         } catch (RemoteException ex) {
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 4ac4850..22ce39d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -917,8 +917,17 @@
      * @see #getDocumentId(Uri)
      */
     public static Uri buildDocumentUri(String authority, String documentId) {
+        return getBaseDocumentUriBuilder(authority).appendPath(documentId).build();
+    }
+
+    /** {@hide} */
+    public static Uri buildBaseDocumentUri(String authority) {
+        return getBaseDocumentUriBuilder(authority).build();
+    }
+
+    private static Uri.Builder getBaseDocumentUriBuilder(String authority) {
         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(authority).appendPath(PATH_DOCUMENT).appendPath(documentId).build();
+            .authority(authority).appendPath(PATH_DOCUMENT);
     }
 
     /**
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 02ce873..08d9733 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -29,6 +29,7 @@
 import android.annotation.TestApi;
 import android.app.Service;
 import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.os.Binder;
@@ -40,6 +41,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseIntArray;
+import android.util.StatsLog;
 import android.view.contentcapture.ContentCaptureCondition;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureEvent;
@@ -114,6 +116,9 @@
     private Handler mHandler;
     private IContentCaptureServiceCallback mCallback;
 
+    private long mCallerMismatchTimeout = 1000;
+    private long mLastCallerMismatchLog;
+
     /**
      * Binder that receives calls from the system server.
      */
@@ -176,9 +181,10 @@
             new IContentCaptureDirectManager.Stub() {
 
         @Override
-        public void sendEvents(@SuppressWarnings("rawtypes") ParceledListSlice events) {
+        public void sendEvents(@SuppressWarnings("rawtypes") ParceledListSlice events, int reason,
+                ContentCaptureOptions options) {
             mHandler.sendMessage(obtainMessage(ContentCaptureService::handleSendEvents,
-                            ContentCaptureService.this, Binder.getCallingUid(), events));
+                    ContentCaptureService.this, Binder.getCallingUid(), events, reason, options));
         }
     };
 
@@ -424,14 +430,23 @@
     }
 
     private void handleSendEvents(int uid,
-            @NonNull ParceledListSlice<ContentCaptureEvent> parceledEvents) {
+            @NonNull ParceledListSlice<ContentCaptureEvent> parceledEvents, int reason,
+            @Nullable ContentCaptureOptions options) {
+        final List<ContentCaptureEvent> events = parceledEvents.getList();
+        if (events.isEmpty()) {
+            Log.w(TAG, "handleSendEvents() received empty list of events");
+            return;
+        }
+
+        // Metrics.
+        final FlushMetrics metrics = new FlushMetrics();
+        ComponentName activityComponent = null;
 
         // Most events belong to the same session, so we can keep a reference to the last one
         // to avoid creating too many ContentCaptureSessionId objects
         int lastSessionId = NO_SESSION_ID;
         ContentCaptureSessionId sessionId = null;
 
-        final List<ContentCaptureEvent> events = parceledEvents.getList();
         for (int i = 0; i < events.size(); i++) {
             final ContentCaptureEvent event = events.get(i);
             if (!handleIsRightCallerFor(event, uid)) continue;
@@ -439,22 +454,44 @@
             if (sessionIdInt != lastSessionId) {
                 sessionId = new ContentCaptureSessionId(sessionIdInt);
                 lastSessionId = sessionIdInt;
+                if (i != 0) {
+                    writeFlushMetrics(lastSessionId, activityComponent, metrics, options, reason);
+                    metrics.reset();
+                }
+            }
+            final ContentCaptureContext clientContext = event.getContentCaptureContext();
+            if (activityComponent == null && clientContext != null) {
+                activityComponent = clientContext.getActivityComponent();
             }
             switch (event.getType()) {
                 case ContentCaptureEvent.TYPE_SESSION_STARTED:
-                    final ContentCaptureContext clientContext = event.getContentCaptureContext();
                     clientContext.setParentSessionId(event.getParentSessionId());
                     mSessionUids.put(sessionIdInt, uid);
                     onCreateContentCaptureSession(clientContext, sessionId);
+                    metrics.sessionStarted++;
                     break;
                 case ContentCaptureEvent.TYPE_SESSION_FINISHED:
                     mSessionUids.delete(sessionIdInt);
                     onDestroyContentCaptureSession(sessionId);
+                    metrics.sessionFinished++;
+                    break;
+                case ContentCaptureEvent.TYPE_VIEW_APPEARED:
+                    onContentCaptureEvent(sessionId, event);
+                    metrics.viewAppearedCount++;
+                    break;
+                case ContentCaptureEvent.TYPE_VIEW_DISAPPEARED:
+                    onContentCaptureEvent(sessionId, event);
+                    metrics.viewDisappearedCount++;
+                    break;
+                case ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED:
+                    onContentCaptureEvent(sessionId, event);
+                    metrics.viewTextChangedCount++;
                     break;
                 default:
                     onContentCaptureEvent(sessionId, event);
             }
         }
+        writeFlushMetrics(lastSessionId, activityComponent, metrics, options, reason);
     }
 
     private void handleOnActivitySnapshot(int sessionId, @NonNull SnapshotData snapshotData) {
@@ -499,7 +536,13 @@
         if (rightUid != uid) {
             Log.e(TAG, "invalid call from UID " + uid + ": session " + sessionId + " belongs to "
                     + rightUid);
-            //TODO(b/111276913): log metrics as this could be a malicious app forging a sessionId
+            long now = System.currentTimeMillis();
+            if (now - mLastCallerMismatchLog > mCallerMismatchTimeout) {
+                StatsLog.write(StatsLog.CONTENT_CAPTURE_CALLER_MISMATCH_REPORTED,
+                        getPackageManager().getNameForUid(rightUid),
+                        getPackageManager().getNameForUid(uid));
+                mLastCallerMismatchLog = now;
+            }
             return false;
         }
         return true;
@@ -530,4 +573,22 @@
             Slog.w(TAG, "Error async reporting result to client: " + e);
         }
     }
+
+    /**
+     * Logs the metrics for content capture events flushing.
+     */
+    private void writeFlushMetrics(int sessionId, @Nullable ComponentName app,
+            @NonNull FlushMetrics flushMetrics, @Nullable ContentCaptureOptions options,
+            int flushReason) {
+        if (mCallback == null) {
+            Log.w(TAG, "writeSessionFlush(): no server callback");
+            return;
+        }
+
+        try {
+            mCallback.writeSessionFlush(sessionId, app, flushMetrics, options, flushReason);
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to write flush metrics: " + e);
+        }
+    }
 }
diff --git a/core/java/android/service/contentcapture/FlushMetrics.aidl b/core/java/android/service/contentcapture/FlushMetrics.aidl
new file mode 100644
index 0000000..d0b935f
--- /dev/null
+++ b/core/java/android/service/contentcapture/FlushMetrics.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+/* @hide */
+parcelable FlushMetrics;
diff --git a/core/java/android/service/contentcapture/FlushMetrics.java b/core/java/android/service/contentcapture/FlushMetrics.java
new file mode 100644
index 0000000..01f3a12
--- /dev/null
+++ b/core/java/android/service/contentcapture/FlushMetrics.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Holds metrics for content capture events flushing.
+ *
+ * @hide
+ */
+public final class FlushMetrics implements Parcelable {
+    public int viewAppearedCount;
+    public int viewDisappearedCount;
+    public int viewTextChangedCount;
+    public int sessionStarted;
+    public int sessionFinished;
+
+    /**
+     * Resets all flush metrics.
+     */
+    public void reset() {
+        viewAppearedCount = 0;
+        viewDisappearedCount = 0;
+        viewTextChangedCount = 0;
+        sessionStarted = 0;
+        sessionFinished = 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(sessionStarted);
+        out.writeInt(sessionFinished);
+        out.writeInt(viewAppearedCount);
+        out.writeInt(viewDisappearedCount);
+        out.writeInt(viewTextChangedCount);
+    }
+
+    @NonNull
+    public static final Creator<FlushMetrics> CREATOR = new Creator<FlushMetrics>() {
+        @NonNull
+        @Override
+        public FlushMetrics createFromParcel(Parcel in) {
+            final FlushMetrics flushMetrics = new FlushMetrics();
+            flushMetrics.sessionStarted = in.readInt();
+            flushMetrics.sessionFinished = in.readInt();
+            flushMetrics.viewAppearedCount = in.readInt();
+            flushMetrics.viewDisappearedCount = in.readInt();
+            flushMetrics.viewTextChangedCount = in.readInt();
+            return flushMetrics;
+        }
+
+        @Override
+        public FlushMetrics[] newArray(int size) {
+            return new FlushMetrics[size];
+        }
+    };
+}
diff --git a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
index 0550ad3..ea6e76b 100644
--- a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
@@ -18,6 +18,8 @@
 
 import android.content.ComponentName;
 import android.view.contentcapture.ContentCaptureCondition;
+import android.service.contentcapture.FlushMetrics;
+import android.content.ContentCaptureOptions;
 
 import java.util.List;
 
@@ -30,4 +32,8 @@
     void setContentCaptureWhitelist(in List<String> packages, in List<ComponentName> activities);
     void setContentCaptureConditions(String packageName, in List<ContentCaptureCondition> conditions);
     void disableSelf();
- }
+
+    // Logs aggregated content capture flush metrics to Statsd
+    void writeSessionFlush(int sessionId, in ComponentName app, in FlushMetrics flushMetrics,
+            in ContentCaptureOptions options, int flushReason);
+}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1812d29..7fdda2a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,7 +33,6 @@
 import android.graphics.RenderNode;
 import android.os.Build;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Looper;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -120,10 +119,11 @@
     final Rect mScreenRect = new Rect();
     SurfaceSession mSurfaceSession;
 
-    SurfaceControlWithBackground mSurfaceControl;
+    SurfaceControl mSurfaceControl;
     // In the case of format changes we switch out the surface in-place
     // we need to preserve the old one until the new one has drawn.
-    SurfaceControlWithBackground mDeferredDestroySurfaceControl;
+    SurfaceControl mDeferredDestroySurfaceControl;
+    SurfaceControl mBackgroundControl;
     final Rect mTmpRect = new Rect();
     final Configuration mConfiguration = new Configuration();
 
@@ -487,6 +487,29 @@
         }
     }
 
+    private void updateBackgroundVisibilityInTransaction(SurfaceControl viewRoot) {
+        if (mBackgroundControl == null) {
+            return;
+        }
+        if ((mSubLayer < 0) && ((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)) {
+            mBackgroundControl.show();
+            mBackgroundControl.setRelativeLayer(viewRoot, Integer.MIN_VALUE);
+        } else {
+            mBackgroundControl.hide();
+        }
+    }
+
+    private void releaseSurfaces() {
+        if (mSurfaceControl != null) {
+            mSurfaceControl.remove();
+            mSurfaceControl = null;
+        }
+        if (mBackgroundControl != null) {
+            mBackgroundControl.remove();
+            mBackgroundControl = null;
+        }
+    }
+
     /** @hide */
     protected void updateSurface() {
         if (!mHaveFrame) {
@@ -553,14 +576,21 @@
                     updateOpaqueFlag();
                     final String name = "SurfaceView - " + viewRoot.getTitle().toString();
 
-                    mSurfaceControl = new SurfaceControlWithBackground(
-                            name,
-                            (mSurfaceFlags & SurfaceControl.OPAQUE) != 0,
-                            new SurfaceControl.Builder(mSurfaceSession)
-                                    .setBufferSize(mSurfaceWidth, mSurfaceHeight)
-                                    .setFormat(mFormat)
-                                    .setParent(viewRoot.getSurfaceControl())
-                                    .setFlags(mSurfaceFlags));
+                    mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
+                        .setName(name)
+                        .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
+                        .setBufferSize(mSurfaceWidth, mSurfaceHeight)
+                        .setFormat(mFormat)
+                        .setParent(viewRoot.getSurfaceControl())
+                        .setFlags(mSurfaceFlags)
+                        .build();
+                    mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
+                        .setName("Background for -" + name)
+                        .setOpaque(true)
+                        .setColorLayer()
+                        .setParent(mSurfaceControl)
+                        .build();
+
                 } else if (mSurfaceControl == null) {
                     return;
                 }
@@ -577,11 +607,13 @@
                     SurfaceControl.openTransaction();
                     try {
                         mSurfaceControl.setLayer(mSubLayer);
+
                         if (mViewVisibility) {
                             mSurfaceControl.show();
                         } else {
                             mSurfaceControl.hide();
                         }
+                        updateBackgroundVisibilityInTransaction(viewRoot.getSurfaceControl());
 
                         // While creating the surface, we will set it's initial
                         // geometry. Outside of that though, we should generally
@@ -667,7 +699,7 @@
                     }
 
                     if (creating) {
-                        mSurface.copyFrom(mSurfaceControl.mForegroundControl);
+                        mSurface.copyFrom(mSurfaceControl);
                     }
 
                     if (sizeChanged && getContext().getApplicationInfo().targetSdkVersion
@@ -677,7 +709,7 @@
                         // existing {@link Surface} will be ignored when the size changes.
                         // Therefore, we must explicitly recreate the {@link Surface} in these
                         // cases.
-                        mSurface.createFrom(mSurfaceControl.mForegroundControl);
+                        mSurface.createFrom(mSurfaceControl);
                     }
 
                     if (visible && mSurface.isValid()) {
@@ -724,8 +756,7 @@
                     if (mSurfaceControl != null && !mSurfaceCreated) {
                         mSurface.release();
 
-                        mSurfaceControl.remove();
-                        mSurfaceControl = null;
+                        releaseSurfaces();
                     }
                 }
             } catch (Exception ex) {
@@ -826,8 +857,7 @@
     private void setParentSpaceRectangle(Rect position, long frameNumber) {
         final ViewRootImpl viewRoot = getViewRootImpl();
 
-        applySurfaceTransforms(mSurfaceControl.mForegroundControl, position, frameNumber);
-        applySurfaceTransforms(mSurfaceControl.mBackgroundControl, position, frameNumber);
+        applySurfaceTransforms(mSurfaceControl, position, frameNumber);
 
         applyChildSurfaceTransaction_renderWorker(mRtTransaction, viewRoot.mSurface,
                 frameNumber);
@@ -892,13 +922,10 @@
             if (frameNumber > 0) {
                 final ViewRootImpl viewRoot = getViewRootImpl();
 
-                mRtTransaction.deferTransactionUntilSurface(mSurfaceControl.mForegroundControl, viewRoot.mSurface,
-                        frameNumber);
-                mRtTransaction.deferTransactionUntilSurface(mSurfaceControl.mBackgroundControl, viewRoot.mSurface,
+                mRtTransaction.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface,
                         frameNumber);
             }
-            mRtTransaction.hide(mSurfaceControl.mForegroundControl);
-            mRtTransaction.hide(mSurfaceControl.mBackgroundControl);
+            mRtTransaction.hide(mSurfaceControl);
             mRtTransaction.apply();
         }
     };
@@ -945,7 +972,19 @@
      * @hide
      */
     public void setResizeBackgroundColor(int bgColor) {
-        mSurfaceControl.setBackgroundColor(bgColor);
+        if (mBackgroundControl == null) {
+            return;
+        }
+
+        final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
+                Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
+
+        SurfaceControl.openTransaction();
+        try {
+            mBackgroundControl.setColor(colorComponents);
+        } finally {
+            SurfaceControl.closeTransaction();
+        }
     }
 
     @UnsupportedAppUsage
@@ -1129,134 +1168,6 @@
      * @return The SurfaceControl for this SurfaceView.
      */
     public SurfaceControl getSurfaceControl() {
-        return mSurfaceControl.mForegroundControl;
-    }
-
-    class SurfaceControlWithBackground {
-        SurfaceControl mForegroundControl;
-        SurfaceControl mBackgroundControl;
-        private boolean mOpaque = true;
-        public boolean mVisible = false;
-
-        public SurfaceControlWithBackground(String name, boolean opaque, SurfaceControl.Builder b)
-                       throws Exception {
-            mForegroundControl = b.setName(name).build();
-            mBackgroundControl = b.setName("Background for -" + name)
-                    // Unset the buffer size of the background color layer.
-                    .setBufferSize(0, 0)
-                    .setColorLayer()
-                    .build();
-
-            mOpaque = opaque;
-        }
-
-        public void setAlpha(float alpha) {
-            mForegroundControl.setAlpha(alpha);
-            mBackgroundControl.setAlpha(alpha);
-        }
-
-        public void setLayer(int zorder) {
-            mForegroundControl.setLayer(zorder);
-            // -3 is below all other child layers as SurfaceView never goes below -2
-            mBackgroundControl.setLayer(-3);
-        }
-
-        public void setPosition(float x, float y) {
-            mForegroundControl.setPosition(x, y);
-            mBackgroundControl.setPosition(x, y);
-        }
-
-        public void setBufferSize(int w, int h) {
-            mForegroundControl.setBufferSize(w, h);
-            // The background surface is a color layer so we do not set a size.
-        }
-
-        public void setWindowCrop(Rect crop) {
-            mForegroundControl.setWindowCrop(crop);
-            mBackgroundControl.setWindowCrop(crop);
-        }
-
-        public void setWindowCrop(int width, int height) {
-            mForegroundControl.setWindowCrop(width, height);
-            mBackgroundControl.setWindowCrop(width, height);
-        }
-
-        public void setLayerStack(int layerStack) {
-            mForegroundControl.setLayerStack(layerStack);
-            mBackgroundControl.setLayerStack(layerStack);
-        }
-
-        public void setOpaque(boolean isOpaque) {
-            mForegroundControl.setOpaque(isOpaque);
-            mOpaque = isOpaque;
-            updateBackgroundVisibility();
-        }
-
-        public void setSecure(boolean isSecure) {
-            mForegroundControl.setSecure(isSecure);
-        }
-
-        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
-            mForegroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
-            mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
-        }
-
-        public void hide() {
-            mForegroundControl.hide();
-            mVisible = false;
-            updateBackgroundVisibility();
-        }
-
-        public void show() {
-            mForegroundControl.show();
-            mVisible = true;
-            updateBackgroundVisibility();
-        }
-
-        public void remove() {
-            mForegroundControl.remove();
-            mBackgroundControl.remove();
-         }
-
-        public void release() {
-            mForegroundControl.release();
-            mBackgroundControl.release();
-        }
-
-        public void setTransparentRegionHint(Region region) {
-            mForegroundControl.setTransparentRegionHint(region);
-            mBackgroundControl.setTransparentRegionHint(region);
-        }
-
-        public void deferTransactionUntil(IBinder handle, long frame) {
-            mForegroundControl.deferTransactionUntil(handle, frame);
-            mBackgroundControl.deferTransactionUntil(handle, frame);
-        }
-
-        public void deferTransactionUntil(Surface barrier, long frame) {
-            mForegroundControl.deferTransactionUntil(barrier, frame);
-            mBackgroundControl.deferTransactionUntil(barrier, frame);
-        }
-
-        /** Set the color to fill the background with. */
-        private void setBackgroundColor(int bgColor) {
-            final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
-                    Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
-
-            SurfaceControl.openTransaction();
-            try {
-                mBackgroundControl.setColor(colorComponents);
-            } finally {
-                SurfaceControl.closeTransaction();
-            }
-        }
-
-        void updateBackgroundVisibility() {
-            if (mOpaque && mVisible) {
-                mBackgroundControl.show();
-            } else {
-                mBackgroundControl.hide();
-            }
-        }
+        return mSurfaceControl;
     }
 }
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 2d292ef..9340b71 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -156,7 +156,9 @@
      * @param src Source to copy insets from
      */
     public WindowInsets(WindowInsets src) {
-        this(src.mTypeInsetsMap, src.mTypeMaxInsetsMap, src.mTypeVisibilityMap, src.mIsRound,
+        this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap,
+                src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
+                src.mTypeVisibilityMap, src.mIsRound,
                 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src));
     }
 
diff --git a/core/java/android/view/contentcapture/IContentCaptureDirectManager.aidl b/core/java/android/view/contentcapture/IContentCaptureDirectManager.aidl
index 8d8117b..959bf13 100644
--- a/core/java/android/view/contentcapture/IContentCaptureDirectManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureDirectManager.aidl
@@ -18,6 +18,7 @@
 
 import android.content.pm.ParceledListSlice;
 import android.view.contentcapture.ContentCaptureEvent;
+import android.content.ContentCaptureOptions;
 
 /**
   * Interface between an app (ContentCaptureManager / ContentCaptureSession) and the app providing
@@ -26,5 +27,6 @@
   * @hide
   */
 oneway interface IContentCaptureDirectManager {
-    void sendEvents(in ParceledListSlice events);
+    // reason and options are used only for metrics logging.
+    void sendEvents(in ParceledListSlice events, int reason, in ContentCaptureOptions options);
 }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 7241664..c5a5f73 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -498,7 +498,7 @@
             }
 
             final ParceledListSlice<ContentCaptureEvent> events = clearEvents();
-            mDirectServiceInterface.sendEvents(events);
+            mDirectServiceInterface.sendEvents(events, reason, mManager.mOptions);
         } catch (RemoteException e) {
             Log.w(TAG, "Error sending " + numberEvents + " for " + getDebugState()
                     + ": " + e);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 20fc0b1..3779779 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -887,6 +887,7 @@
      *
      * @return true if popup will be clipped to the screen instead of the window, false otherwise
      * @deprecated Use {@link #isClippedToScreen()} instead
+     * @removed
      */
     @Deprecated
     public boolean isClipToScreenEnabled() {
@@ -901,6 +902,7 @@
      * the {@link #update()} methods.</p>
      *
      * @deprecated Use {@link #setIsClippedToScreen(boolean)} instead
+     * @removed
      */
     @Deprecated
     public void setClipToScreenEnabled(boolean enabled) {
@@ -988,6 +990,7 @@
      * @return true if the window will always be positioned in screen coordinates.
      *
      * @deprecated Use {@link #isLaidOutInScreen()} instead
+     * @removed
      */
     @Deprecated
     public boolean isLayoutInScreenEnabled() {
@@ -1001,6 +1004,7 @@
      *
      * @param enabled true if the popup should always be positioned in screen coordinates
      * @deprecated Use {@link #setIsLaidOutInScreen(boolean)} instead
+     * @removed
      */
     @Deprecated
     public void setLayoutInScreenEnabled(boolean enabled) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2736c6a..dbc15b3 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -172,6 +172,11 @@
      */
     public static final int SOCKET_BUFFER_SIZE = 256;
 
+    /**
+     * @hide for internal use only
+     */
+    private static final int PRIORITY_MAX = -20;
+
     /** a prototype instance for a future List.toArray() */
     protected static final int[][] INT_ARRAY_2D = new int[0][0];
 
@@ -236,8 +241,7 @@
             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
             int targetSdkVersion) {
         ZygoteHooks.preFork();
-        // Resets nice priority for zygote process.
-        resetNicePriority();
+
         int pid = nativeForkAndSpecialize(
                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                 fdsToIgnore, startChildZygote, instructionSet, appDataDir);
@@ -249,6 +253,7 @@
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
         }
+
         ZygoteHooks.postForkCommon();
         return pid;
     }
@@ -335,15 +340,16 @@
     public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
         ZygoteHooks.preFork();
-        // Resets nice priority for zygote process.
-        resetNicePriority();
+
         int pid = nativeForkSystemServer(
                 uid, gid, gids, runtimeFlags, rlimits,
                 permittedCapabilities, effectiveCapabilities);
+
         // Enable tracing as soon as we enter the system_server.
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
         }
+
         ZygoteHooks.postForkCommon();
         return pid;
     }
@@ -461,13 +467,16 @@
     /**
      * Fork a new unspecialized app process from the zygote
      *
+     * @param usapPoolSocket  The server socket the USAP will call accept on
      * @param sessionSocketRawFDs  Anonymous session sockets that are currently open
+     * @param isPriorityFork  Value controlling the process priority level until accept is called
      * @return In the Zygote process this function will always return null; in unspecialized app
      *         processes this function will return a Runnable object representing the new
      *         application that is passed up from usapMain.
      */
     static Runnable forkUsap(LocalServerSocket usapPoolSocket,
-                             int[] sessionSocketRawFDs) {
+                             int[] sessionSocketRawFDs,
+                             boolean isPriorityFork) {
         FileDescriptor[] pipeFDs = null;
 
         try {
@@ -477,7 +486,8 @@
         }
 
         int pid =
-                nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(), sessionSocketRawFDs);
+                nativeForkUsap(pipeFDs[0].getInt$(), pipeFDs[1].getInt$(),
+                               sessionSocketRawFDs, isPriorityFork);
 
         if (pid == 0) {
             IoUtils.closeQuietly(pipeFDs[0]);
@@ -491,8 +501,9 @@
     }
 
     private static native int nativeForkUsap(int readPipeFD,
-                                                 int writePipeFD,
-                                                 int[] sessionSocketRawFDs);
+                                             int writePipeFD,
+                                             int[] sessionSocketRawFDs,
+                                             boolean isPriorityFork);
 
     /**
      * This function is used by unspecialized app processes to wait for specialization requests from
@@ -515,6 +526,11 @@
         // Load resources
         ZygoteInit.nativePreloadGraphicsDriver();
 
+        // Change the priority to max before calling accept so we can respond to new specialization
+        // requests as quickly as possible.  This will be reverted to the default priority in the
+        // native specialization code.
+        boostUsapPriority();
+
         while (true) {
             try {
                 sessionSocket = usapPoolSocket.accept();
@@ -618,6 +634,12 @@
                                      null /* classLoader */);
     }
 
+    private static void boostUsapPriority() {
+        nativeBoostUsapPriority();
+    }
+
+    private static native void nativeBoostUsapPriority();
+
     private static final String USAP_ERROR_PREFIX = "Invalid command to USAP: ";
 
     /**
@@ -858,15 +880,6 @@
     }
 
     /**
-     * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
-     * or nice value 0). This updates both the priority value in java.lang.Thread and
-     * the nice value (setpriority).
-     */
-    static void resetNicePriority() {
-        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
-    }
-
-    /**
      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
      * This method throws a runtime exception if exec() failed, otherwise, this
      * method never returns.
diff --git a/core/java/com/android/internal/os/ZygoteConfig.java b/core/java/com/android/internal/os/ZygoteConfig.java
index c6af8c2..6ebcae1 100644
--- a/core/java/com/android/internal/os/ZygoteConfig.java
+++ b/core/java/com/android/internal/os/ZygoteConfig.java
@@ -34,4 +34,7 @@
 
     /** The minimum number of processes to keep in the USAP pool */
     public static final String USAP_POOL_SIZE_MIN = "usap_pool_size_min";
+
+    /** The number of milliseconds to delay before refilling the USAP pool */
+    public static final String USAP_POOL_REFILL_DELAY_MS = "usap_pool_refill_delay_ms";
 }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 785256e..1a8ba76 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -346,7 +346,7 @@
             if (zygoteServer.isUsapPoolEnabled()) {
                 Runnable fpResult =
                         zygoteServer.fillUsapPool(
-                                new int[]{mSocket.getFileDescriptor().getInt$()});
+                                new int[]{mSocket.getFileDescriptor().getInt$()}, false);
 
                 if (fpResult != null) {
                     zygoteServer.setForkChild();
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index f9e868f..c5a0af7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -822,6 +822,9 @@
     public static void main(String argv[]) {
         ZygoteServer zygoteServer = null;
 
+        // Set the initial thread priority to the "normal" value.
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+
         // Mark zygote start. This ensures that thread creation will throw
         // an error.
         ZygoteHooks.startZygoteNoThreadCreation();
@@ -881,8 +884,6 @@
                 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                         SystemClock.uptimeMillis());
                 bootTimingsTraceLog.traceEnd(); // ZygotePreload
-            } else {
-                Zygote.resetNicePriority();
             }
 
             // Do an initial gc to clean up after startup
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 5d1911b..492bc94 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -66,6 +66,12 @@
     /** The default value used for the USAP_POOL_SIZE_MIN device property */
     private static final String USAP_POOL_SIZE_MIN_DEFAULT = "1";
 
+    /** The default value used for the USAP_REFILL_DELAY_MS device property */
+    private static final String USAP_POOL_REFILL_DELAY_MS_DEFAULT = "3000";
+
+    /** The "not a timestamp" value for the refill delay timestamp mechanism. */
+    private static final int INVALID_TIMESTAMP = -1;
+
     /**
      * Indicates if this Zygote server can support a unspecialized app process pool.  Currently this
      * should only be true for the primary and secondary Zygotes, and not the App Zygotes or the
@@ -131,6 +137,18 @@
      */
     private int mUsapPoolRefillThreshold = 0;
 
+    /**
+     * Number of milliseconds to delay before refilling the pool if it hasn't reached its
+     * minimum value.
+     */
+    private int mUsapPoolRefillDelayMs = -1;
+
+    private enum UsapPoolRefillAction {
+        DELAYED,
+        IMMEDIATE,
+        NONE
+    }
+
     ZygoteServer() {
         mUsapPoolEventFD = null;
         mZygoteSocket = null;
@@ -267,6 +285,13 @@
                         mUsapPoolSizeMax);
             }
 
+            final String usapPoolRefillDelayMsPropString = Zygote.getConfigurationProperty(
+                    ZygoteConfig.USAP_POOL_REFILL_DELAY_MS, USAP_POOL_REFILL_DELAY_MS_DEFAULT);
+
+            if (!usapPoolRefillDelayMsPropString.isEmpty()) {
+                mUsapPoolRefillDelayMs = Integer.parseInt(usapPoolRefillDelayMsPropString);
+            }
+
             // Sanity check
             if (mUsapPoolSizeMin >= mUsapPoolSizeMax) {
                 Log.w(TAG, "The max size of the USAP pool must be greater than the minimum size."
@@ -293,9 +318,16 @@
         }
     }
 
+    private void fetchUsapPoolPolicyPropsIfUnfetched() {
+        if (mIsFirstPropertyCheck) {
+            mIsFirstPropertyCheck = false;
+            fetchUsapPoolPolicyProps();
+        }
+    }
+
     /**
-     * Checks to see if the current policy says that pool should be refilled, and spawns new USAPs
-     * if necessary.
+     * Refill the USAP Pool to the appropriate level, determined by whether this is a priority
+     * refill event or not.
      *
      * @param sessionSocketRawFDs  Anonymous session sockets that are currently open
      * @return In the Zygote process this function will always return null; in unspecialized app
@@ -303,39 +335,46 @@
      *         application that is passed up from usapMain.
      */
 
-    Runnable fillUsapPool(int[] sessionSocketRawFDs) {
+    Runnable fillUsapPool(int[] sessionSocketRawFDs, boolean isPriorityRefill) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillUsapPool");
 
         // Ensure that the pool properties have been fetched.
-        fetchUsapPoolPolicyPropsWithMinInterval();
+        fetchUsapPoolPolicyPropsIfUnfetched();
 
         int usapPoolCount = Zygote.getUsapPoolCount();
-        int numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
+        int numUsapsToSpawn;
 
-        if (usapPoolCount < mUsapPoolSizeMin
-                || numUsapsToSpawn >= mUsapPoolRefillThreshold) {
-
-            // Disable some VM functionality and reset some system values
-            // before forking.
-            ZygoteHooks.preFork();
-            Zygote.resetNicePriority();
-
-            while (usapPoolCount++ < mUsapPoolSizeMax) {
-                Runnable caller = Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs);
-
-                if (caller != null) {
-                    return caller;
-                }
-            }
-
-            // Re-enable runtime services for the Zygote.  Services for unspecialized app process
-            // are re-enabled in specializeAppProcess.
-            ZygoteHooks.postForkCommon();
+        if (isPriorityRefill) {
+            // Refill to min
+            numUsapsToSpawn = mUsapPoolSizeMin - usapPoolCount;
 
             Log.i("zygote",
-                    "Filled the USAP pool. New USAPs: " + numUsapsToSpawn);
+                    "Priority USAP Pool refill. New USAPs: " + numUsapsToSpawn);
+        } else {
+            // Refill up to max
+            numUsapsToSpawn = mUsapPoolSizeMax - usapPoolCount;
+
+            Log.i("zygote",
+                    "Delayed USAP Pool refill. New USAPs: " + numUsapsToSpawn);
         }
 
+        // Disable some VM functionality and reset some system values
+        // before forking.
+        ZygoteHooks.preFork();
+
+        while (--numUsapsToSpawn >= 0) {
+            Runnable caller =
+                    Zygote.forkUsap(mUsapPoolSocket, sessionSocketRawFDs, isPriorityRefill);
+
+            if (caller != null) {
+                return caller;
+            }
+        }
+
+        // Re-enable runtime services for the Zygote.  Services for unspecialized app process
+        // are re-enabled in specializeAppProcess.
+        ZygoteHooks.postForkCommon();
+
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
         return null;
@@ -358,7 +397,7 @@
         mUsapPoolEnabled = newStatus;
 
         if (newStatus) {
-            return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() });
+            return fillUsapPool(new int[]{ sessionSocket.getFileDescriptor().getInt$() }, false);
         } else {
             Zygote.emptyUsapPool();
             return null;
@@ -377,6 +416,8 @@
         socketFDs.add(mZygoteSocket.getFileDescriptor());
         peers.add(null);
 
+        long usapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
+
         while (true) {
             fetchUsapPoolPolicyPropsWithMinInterval();
 
@@ -428,140 +469,192 @@
                 }
             }
 
+            int pollTimeoutMs;
+
+            if (usapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
+                pollTimeoutMs = -1;
+            } else {
+                int elapsedTimeMs =
+                        (int) (System.currentTimeMillis() - usapPoolRefillTriggerTimestamp);
+
+                if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
+                    // Normalize the poll timeout value when the time between one poll event and the
+                    // next pushes us over the delay value.  This prevents poll receiving a 0
+                    // timeout value, which would result in it returning immediately.
+                    pollTimeoutMs = -1;
+                } else {
+                    pollTimeoutMs = mUsapPoolRefillDelayMs - elapsedTimeMs;
+                }
+            }
+
+            int pollReturnValue;
             try {
-                Os.poll(pollFDs, -1);
+                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
             } catch (ErrnoException ex) {
                 throw new RuntimeException("poll failed", ex);
             }
 
-            boolean usapPoolFDRead = false;
+            UsapPoolRefillAction usapPoolRefillAction = UsapPoolRefillAction.NONE;
+            if (pollReturnValue == 0) {
+                // The poll timeout has been exceeded.  This only occurs when we have finished the
+                // USAP pool refill delay period.
 
-            while (--pollIndex >= 0) {
-                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
-                    continue;
-                }
+                usapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
+                usapPoolRefillAction = UsapPoolRefillAction.DELAYED;
 
-                if (pollIndex == 0) {
-                    // Zygote server socket
+            } else {
+                boolean usapPoolFDRead = false;
 
-                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
-                    peers.add(newPeer);
-                    socketFDs.add(newPeer.getFileDescriptor());
-
-                } else if (pollIndex < usapPoolEventFDIndex) {
-                    // Session socket accepted from the Zygote server socket
-
-                    try {
-                        ZygoteConnection connection = peers.get(pollIndex);
-                        final Runnable command = connection.processOneCommand(this);
-
-                        // TODO (chriswailes): Is this extra check necessary?
-                        if (mIsForkChild) {
-                            // We're in the child. We should always have a command to run at this
-                            // stage if processOneCommand hasn't called "exec".
-                            if (command == null) {
-                                throw new IllegalStateException("command == null");
-                            }
-
-                            return command;
-                        } else {
-                            // We're in the server - we should never have any commands to run.
-                            if (command != null) {
-                                throw new IllegalStateException("command != null");
-                            }
-
-                            // We don't know whether the remote side of the socket was closed or
-                            // not until we attempt to read from it from processOneCommand. This
-                            // shows up as a regular POLLIN event in our regular processing loop.
-                            if (connection.isClosedByPeer()) {
-                                connection.closeSocket();
-                                peers.remove(pollIndex);
-                                socketFDs.remove(pollIndex);
-                            }
-                        }
-                    } catch (Exception e) {
-                        if (!mIsForkChild) {
-                            // We're in the server so any exception here is one that has taken place
-                            // pre-fork while processing commands or reading / writing from the
-                            // control socket. Make a loud noise about any such exceptions so that
-                            // we know exactly what failed and why.
-
-                            Slog.e(TAG, "Exception executing zygote command: ", e);
-
-                            // Make sure the socket is closed so that the other end knows
-                            // immediately that something has gone wrong and doesn't time out
-                            // waiting for a response.
-                            ZygoteConnection conn = peers.remove(pollIndex);
-                            conn.closeSocket();
-
-                            socketFDs.remove(pollIndex);
-                        } else {
-                            // We're in the child so any exception caught here has happened post
-                            // fork and before we execute ActivityThread.main (or any other main()
-                            // method). Log the details of the exception and bring down the process.
-                            Log.e(TAG, "Caught post-fork exception in child process.", e);
-                            throw e;
-                        }
-                    } finally {
-                        // Reset the child flag, in the event that the child process is a child-
-                        // zygote. The flag will not be consulted this loop pass after the Runnable
-                        // is returned.
-                        mIsForkChild = false;
-                    }
-                } else {
-                    // Either the USAP pool event FD or a USAP reporting pipe.
-
-                    // If this is the event FD the payload will be the number of USAPs removed.
-                    // If this is a reporting pipe FD the payload will be the PID of the USAP
-                    // that was just specialized.
-                    long messagePayload = -1;
-
-                    try {
-                        byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
-                        int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
-
-                        if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
-                            DataInputStream inputStream =
-                                    new DataInputStream(new ByteArrayInputStream(buffer));
-
-                            messagePayload = inputStream.readLong();
-                        } else {
-                            Log.e(TAG, "Incomplete read from USAP management FD of size "
-                                    + readBytes);
-                            continue;
-                        }
-                    } catch (Exception ex) {
-                        if (pollIndex == usapPoolEventFDIndex) {
-                            Log.e(TAG, "Failed to read from USAP pool event FD: "
-                                    + ex.getMessage());
-                        } else {
-                            Log.e(TAG, "Failed to read from USAP reporting pipe: "
-                                    + ex.getMessage());
-                        }
-
+                while (--pollIndex >= 0) {
+                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                         continue;
                     }
 
-                    if (pollIndex > usapPoolEventFDIndex) {
-                        Zygote.removeUsapTableEntry((int) messagePayload);
-                    }
+                    if (pollIndex == 0) {
+                        // Zygote server socket
 
-                    usapPoolFDRead = true;
+                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
+                        peers.add(newPeer);
+                        socketFDs.add(newPeer.getFileDescriptor());
+
+                    } else if (pollIndex < usapPoolEventFDIndex) {
+                        // Session socket accepted from the Zygote server socket
+
+                        try {
+                            ZygoteConnection connection = peers.get(pollIndex);
+                            final Runnable command = connection.processOneCommand(this);
+
+                            // TODO (chriswailes): Is this extra check necessary?
+                            if (mIsForkChild) {
+                                // We're in the child. We should always have a command to run at
+                                // this stage if processOneCommand hasn't called "exec".
+                                if (command == null) {
+                                    throw new IllegalStateException("command == null");
+                                }
+
+                                return command;
+                            } else {
+                                // We're in the server - we should never have any commands to run.
+                                if (command != null) {
+                                    throw new IllegalStateException("command != null");
+                                }
+
+                                // We don't know whether the remote side of the socket was closed or
+                                // not until we attempt to read from it from processOneCommand. This
+                                // shows up as a regular POLLIN event in our regular processing
+                                // loop.
+                                if (connection.isClosedByPeer()) {
+                                    connection.closeSocket();
+                                    peers.remove(pollIndex);
+                                    socketFDs.remove(pollIndex);
+                                }
+                            }
+                        } catch (Exception e) {
+                            if (!mIsForkChild) {
+                                // We're in the server so any exception here is one that has taken
+                                // place pre-fork while processing commands or reading / writing
+                                // from the control socket. Make a loud noise about any such
+                                // exceptions so that we know exactly what failed and why.
+
+                                Slog.e(TAG, "Exception executing zygote command: ", e);
+
+                                // Make sure the socket is closed so that the other end knows
+                                // immediately that something has gone wrong and doesn't time out
+                                // waiting for a response.
+                                ZygoteConnection conn = peers.remove(pollIndex);
+                                conn.closeSocket();
+
+                                socketFDs.remove(pollIndex);
+                            } else {
+                                // We're in the child so any exception caught here has happened post
+                                // fork and before we execute ActivityThread.main (or any other
+                                // main() method). Log the details of the exception and bring down
+                                // the process.
+                                Log.e(TAG, "Caught post-fork exception in child process.", e);
+                                throw e;
+                            }
+                        } finally {
+                            // Reset the child flag, in the event that the child process is a child-
+                            // zygote. The flag will not be consulted this loop pass after the
+                            // Runnable is returned.
+                            mIsForkChild = false;
+                        }
+                    } else {
+                        // Either the USAP pool event FD or a USAP reporting pipe.
+
+                        // If this is the event FD the payload will be the number of USAPs removed.
+                        // If this is a reporting pipe FD the payload will be the PID of the USAP
+                        // that was just specialized.  The `continue` statements below ensure that
+                        // the messagePayload will always be valid if we complete the try block
+                        // without an exception.
+                        long messagePayload;
+
+                        try {
+                            byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
+                            int readBytes =
+                                    Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
+
+                            if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
+                                DataInputStream inputStream =
+                                        new DataInputStream(new ByteArrayInputStream(buffer));
+
+                                messagePayload = inputStream.readLong();
+                            } else {
+                                Log.e(TAG, "Incomplete read from USAP management FD of size "
+                                        + readBytes);
+                                continue;
+                            }
+                        } catch (Exception ex) {
+                            if (pollIndex == usapPoolEventFDIndex) {
+                                Log.e(TAG, "Failed to read from USAP pool event FD: "
+                                        + ex.getMessage());
+                            } else {
+                                Log.e(TAG, "Failed to read from USAP reporting pipe: "
+                                        + ex.getMessage());
+                            }
+
+                            continue;
+                        }
+
+                        if (pollIndex > usapPoolEventFDIndex) {
+                            Zygote.removeUsapTableEntry((int) messagePayload);
+                        }
+
+                        usapPoolFDRead = true;
+                    }
+                }
+
+                if (usapPoolFDRead) {
+                    int usapPoolCount = Zygote.getUsapPoolCount();
+
+                    if (usapPoolCount < mUsapPoolSizeMin) {
+                        // Immediate refill
+                        usapPoolRefillAction = UsapPoolRefillAction.IMMEDIATE;
+                    } else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
+                        // Delayed refill
+                        usapPoolRefillTriggerTimestamp = System.currentTimeMillis();
+                    }
                 }
             }
 
-            // Check to see if the USAP pool needs to be refilled.
-            if (usapPoolFDRead) {
+            if (usapPoolRefillAction != UsapPoolRefillAction.NONE) {
                 int[] sessionSocketRawFDs =
                         socketFDs.subList(1, socketFDs.size())
                                 .stream()
                                 .mapToInt(fd -> fd.getInt$())
                                 .toArray();
 
-                final Runnable command = fillUsapPool(sessionSocketRawFDs);
+                final boolean isPriorityRefill =
+                        usapPoolRefillAction == UsapPoolRefillAction.IMMEDIATE;
+
+                final Runnable command =
+                        fillUsapPool(sessionSocketRawFDs, isPriorityRefill);
 
                 if (command != null) {
                     return command;
+                } else if (isPriorityRefill) {
+                    // Schedule a delayed refill to finish refilling the pool.
+                    usapPoolRefillTriggerTimestamp = System.currentTimeMillis();
                 }
             }
         }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 8ff1691..5267427 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -169,6 +169,15 @@
  */
 static constexpr int USAP_POOL_SIZE_MAX_LIMIT = 100;
 
+/** The numeric value for the maximum priority a process may possess. */
+static constexpr int PROCESS_PRIORITY_MAX = -20;
+
+/** The numeric value for the minimum priority a process may possess. */
+static constexpr int PROCESS_PRIORITY_MIN = 19;
+
+/** The numeric value for the normal priority a process should have. */
+static constexpr int PROCESS_PRIORITY_DEFAULT = 0;
+
 /**
  * A helper class containing accounting information for USAPs.
  */
@@ -893,7 +902,8 @@
 // Utility routine to fork a process from the zygote.
 static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
-                        const std::vector<int>& fds_to_ignore) {
+                        const std::vector<int>& fds_to_ignore,
+                        bool is_priority_fork) {
   SetSignalHandlers();
 
   // Curry a failure function.
@@ -926,6 +936,12 @@
   pid_t pid = fork();
 
   if (pid == 0) {
+    if (is_priority_fork) {
+      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+    } else {
+      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
+    }
+
     // The child process.
     PreApplicationInit();
 
@@ -1123,6 +1139,9 @@
   env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                             is_system_server, is_child_zygote, managed_instruction_set);
 
+  // Reset the process priority to the default value.
+  setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
+
   if (env->ExceptionCheck()) {
     fail_fn("Error calling post fork hooks.");
   }
@@ -1360,7 +1379,7 @@
       fds_to_ignore.push_back(gUsapPoolEventFD);
     }
 
-    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);
+    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true);
 
     if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
@@ -1387,7 +1406,8 @@
 
   pid_t pid = ForkCommon(env, true,
                          fds_to_close,
-                         fds_to_ignore);
+                         fds_to_ignore,
+                         true);
   if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        permitted_capabilities, effective_capabilities,
@@ -1429,13 +1449,15 @@
  * zygote in managed code.
  * @param managed_session_socket_fds  A list of anonymous session sockets that must be ignored by
  * the FD hygiene code and automatically "closed" in the new USAP.
+ * @param is_priority_fork  Controls the nice level assigned to the newly created process
  * @return
  */
 static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env,
                                                           jclass,
                                                           jint read_pipe_fd,
                                                           jint write_pipe_fd,
-                                                          jintArray managed_session_socket_fds) {
+                                                          jintArray managed_session_socket_fds,
+                                                          jboolean is_priority_fork) {
   std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
                    fds_to_ignore(fds_to_close);
 
@@ -1457,7 +1479,8 @@
   fds_to_ignore.push_back(write_pipe_fd);
   fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end());
 
-  pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore);
+  pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
+                              is_priority_fork == JNI_TRUE);
 
   if (usap_pid != 0) {
     ++gUsapPoolCount;
@@ -1678,6 +1701,10 @@
   return dl_iterate_phdr(disable_execute_only, nullptr) == 0;
 }
 
+static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, jclass) {
+  setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
+}
+
 static const JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I",
@@ -1690,7 +1717,7 @@
       (void *) com_android_internal_os_Zygote_nativePreApplicationInit },
     { "nativeInstallSeccompUidGidFilter", "(II)V",
       (void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter },
-    { "nativeForkUsap", "(II[I)I",
+    { "nativeForkUsap", "(II[IZ)I",
       (void *) com_android_internal_os_Zygote_nativeForkUsap },
     { "nativeSpecializeAppProcess",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V",
@@ -1708,7 +1735,9 @@
     { "nativeEmptyUsapPool", "()V",
       (void *) com_android_internal_os_Zygote_nativeEmptyUsapPool },
     { "nativeDisableExecuteOnly", "()Z",
-      (void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly }
+      (void *) com_android_internal_os_Zygote_nativeDisableExecuteOnly },
+    { "nativeBoostUsapPriority", "()V",
+      (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority }
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index d903524..d4c3565 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -26,17 +26,17 @@
         android:id="@+id/autofill_save"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="32dp"
-        android:paddingTop="16dp"
-        android:elevation="32dp"
+        android:layout_marginTop="@dimen/autofill_save_outer_top_margin"
+        android:paddingTop="@dimen/autofill_save_outer_top_padding"
+        android:elevation="@dimen/autofill_elevation"
         android:background="?android:attr/colorBackground"
         android:orientation="vertical">
 
         <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
-            android:paddingStart="16dp"
-            android:paddingEnd="16dp"
+            android:paddingStart="@dimen/autofill_save_inner_padding"
+            android:paddingEnd="@dimen/autofill_save_inner_padding"
             android:orientation="vertical">
 
             <LinearLayout
@@ -47,17 +47,16 @@
                 <ImageView
                     android:id="@+id/autofill_save_icon"
                     android:scaleType="fitStart"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"/>
+                    android:layout_width="@dimen/autofill_save_icon_size"
+                    android:layout_height="@dimen/autofill_save_icon_size"/>
 
                 <TextView
                     android:id="@+id/autofill_save_title"
-                    android:paddingStart="8dp"
+                    android:paddingStart="@dimen/autofill_save_title_start_padding"
                     android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/autofill_save_title"
-                    android:textSize="16sp"
-                    android:textColor="?android:attr/textColorPrimary"
+                    android:textAppearance="@style/TextAppearance.DeviceDefault.Subhead"
                     android:layout_weight="1">
                 </TextView>
 
@@ -67,7 +66,7 @@
                 android:id="@+id/autofill_save_custom_subtitle"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="4dp"
+                android:layout_marginTop="@dimen/autofill_save_scroll_view_top_margin"
                 android:visibility="gone"/>
 
         </LinearLayout>
@@ -76,7 +75,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="end"
-            android:padding="16dp"
+            android:padding="@dimen/autofill_save_button_bar_padding"
             android:clipToPadding="false"
             android:layout_weight="1"
             android:orientation="horizontal">
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 167e672..6f11432 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -73,6 +73,11 @@
     <dimen name="navigation_bar_width_car_mode">96dp</dimen>
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">22dip</dimen>
+    <!-- Desired size of system icons in status bar. -->
+    <dimen name="status_bar_system_icon_size">15dp</dimen>
+    <!-- Intrinsic size of most system icons in status bar. This is the default value that
+         is used if a Drawable reports an intrinsic size of 0. -->
+    <dimen name="status_bar_system_icon_intrinsic_size">17dp</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
@@ -668,6 +673,16 @@
     <dimen name="autofill_dataset_picker_max_width">90%</dimen>
     <dimen name="autofill_dataset_picker_max_height">90%</dimen>
 
+    <!-- Autofill save dialog padding -->
+    <dimen name="autofill_save_outer_top_margin">32dp</dimen>
+    <dimen name="autofill_save_outer_top_padding">16dp</dimen>
+    <dimen name="autofill_elevation">32dp</dimen>
+    <dimen name="autofill_save_inner_padding">16dp</dimen>
+    <dimen name="autofill_save_icon_size">24dp</dimen>
+    <dimen name="autofill_save_title_start_padding">8dp</dimen>
+    <dimen name="autofill_save_scroll_view_top_margin">4dp</dimen>
+    <dimen name="autofill_save_button_bar_padding">16dp</dimen>
+
     <!-- Max height of the the autofill save custom subtitle as a fraction of the screen width/height -->
     <dimen name="autofill_save_custom_subtitle_max_height">20%</dimen>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 33bc341..fb54566 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2889,6 +2889,99 @@
 
   <!-- ===============================================================
        Resources added in version Q of the platform
+       =============================================================== -->
+    <eat-comment />
+
+    <public type="attr" name="packageType" id="0x01010587" />
+    <public type="attr" name="opticalInsetLeft" id="0x01010588" />
+    <public type="attr" name="opticalInsetTop" id="0x01010589" />
+    <public type="attr" name="opticalInsetRight" id="0x0101058a" />
+    <public type="attr" name="opticalInsetBottom" id="0x0101058b" />
+    <public type="attr" name="forceDarkAllowed" id="0x0101058c" />
+    <!-- @hide @SystemApi -->
+    <public type="attr" name="supportsAmbientMode" id="0x0101058d" />
+    <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
+    <public type="attr" name="usesNonSdkApi" id="0x0101058e" />
+    <public type="attr" name="nonInteractiveUiTimeout" id="0x0101058f" />
+    <public type="attr" name="isLightTheme" id="0x01010590" />
+    <public type="attr" name="isSplitRequired" id="0x01010591" />
+    <public type="attr" name="textLocale" id="0x01010592" />
+    <public type="attr" name="settingsSliceUri" id="0x01010593" />
+    <public type="attr" name="shell" id="0x01010594" />
+    <public type="attr" name="interactiveUiTimeout" id="0x01010595" />
+    <public type="attr" name="supportsMultipleDisplays" id="0x01010596" />
+    <public type="attr" name="useAppZygote" id="0x01010597" />
+    <public type="attr" name="selectionDividerHeight" id="0x01010598" />
+    <public type="attr" name="foregroundServiceType" id="0x01010599" />
+    <public type="attr" name="hasFragileUserData" id="0x0101059a" />
+    <public type="attr" name="minAspectRatio" id="0x0101059b" />
+    <public type="attr" name="inheritShowWhenLocked" id="0x0101059c" />
+    <public type="attr" name="zygotePreloadName" id="0x0101059d" />
+    <public type="attr" name="useEmbeddedDex" id="0x0101059e" />
+    <public type="attr" name="forceUriPermissions" id="0x0101059f" />
+    <!-- @hide @SystemApi -->
+    <public type="attr" name="allowClearUserDataOnFailedRestore" id="0x01010600" />
+    <public type="attr" name="allowAudioPlaybackCapture" id="0x01010601" />
+    <public type="attr" name="secureElementName" id="0x01010602" />
+    <public type="attr" name="requestLegacyExternalStorage" id="0x01010603" />
+    <public type="attr" name="enforceStatusBarContrast" id="0x01010604" />
+    <public type="attr" name="enforceNavigationBarContrast" id="0x01010605" />
+    <public type="attr" name="identifier" id="0x01010606" />
+
+    <!-- @hide @SystemApi -->
+    <public type="drawable" name="ic_info" id="0x010800b4" />
+
+    <!-- @hide @SystemApi -->
+    <public type="style" name="Theme.DeviceDefault.DocumentsUI" id="0x010302e2" />
+    <public type="style" name="Theme.DeviceDefault.DayNight" id="0x010302e3" />
+    <public type="style" name="ThemeOverlay.DeviceDefault.Accent.DayNight" id="0x010302e4" />
+
+    <public type="id" name="accessibilityActionPageUp" id="0x01020046" />
+    <public type="id" name="accessibilityActionPageDown" id="0x01020047" />
+    <public type="id" name="accessibilityActionPageLeft" id="0x01020048" />
+    <public type="id" name="accessibilityActionPageRight" id="0x01020049" />
+
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_helpPackageNameKey" id="0x0104001b" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_helpPackageNameValue" id="0x0104001c" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_helpIntentExtraKey" id="0x0104001d" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_helpIntentNameKey" id="0x0104001e" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_feedbackIntentExtraKey" id="0x0104001f" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_feedbackIntentNameKey" id="0x01040020" />
+    <!-- @hide @SystemApi @TestApi -->
+    <public type="string" name="config_defaultAssistant" id="0x01040021" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_defaultBrowser" id="0x01040022" />
+    <!-- @hide @SystemApi @TestApi -->
+    <public type="string" name="config_defaultDialer" id="0x01040023" />
+    <!-- @hide @SystemApi -->
+    <public type="string" name="config_defaultSms" id="0x01040024" />
+
+    <!-- @hide @SystemApi -->
+    <public type="bool" name="config_sendPackageName" id="0x01110000" />
+    <!-- @hide @SystemApi -->
+    <public type="bool" name="config_showDefaultAssistant" id="0x01110001" />
+    <!-- @hide @SystemApi -->
+    <public type="bool" name="config_showDefaultEmergency" id="0x01110002" />
+    <!-- @hide @SystemApi -->
+    <public type="bool" name="config_showDefaultHome" id="0x01110003" />
+    <!-- @hide @TestApi -->
+    <public type="bool" name="config_perDisplayFocusEnabled" id="0x01110004" />
+
+    <!-- @hide @SystemApi -->
+    <public type="dimen" name="config_restrictedIconSize" id="0x01050007" />
+
+    <!-- @hide @SystemApi -->
+    <public type="color" name="system_notification_accent_color" id="0x0106001c" />
+
+
+  <!-- ===============================================================
+       Resources added in version R of the platform
 
        NOTE: add <public> elements within a <public-group> like so:
 
@@ -2904,113 +2997,28 @@
        =============================================================== -->
   <eat-comment />
 
-    <public-group type="attr" first-id="0x01010587">
-        <public name="packageType" />
-        <public name="opticalInsetLeft" />
-        <public name="opticalInsetTop" />
-        <public name="opticalInsetRight" />
-        <public name="opticalInsetBottom" />
-        <public name="forceDarkAllowed" />
-        <!-- @hide @SystemApi -->
-        <public name="supportsAmbientMode" />
-        <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
-        <public name="usesNonSdkApi" />
-        <public name="nonInteractiveUiTimeout" />
-        <public name="isLightTheme" />
-        <public name="isSplitRequired" />
-        <public name="textLocale" />
-        <public name="settingsSliceUri" />
-        <public name="shell" />
-        <public name="interactiveUiTimeout" />
-        <public name="__removed6" />
-        <public name="supportsMultipleDisplays" />
-        <public name="useAppZygote" />
-        <public name="__removed1" />
-        <public name="__removed2" />
-        <public name="__removed3" />
-        <public name="__removed4" />
-        <public name="__removed5" />
-        <public name="selectionDividerHeight" />
-        <public name="foregroundServiceType" />
-        <public name="hasFragileUserData" />
-        <public name="minAspectRatio" />
-        <public name="inheritShowWhenLocked" />
-        <public name="zygotePreloadName" />
-        <public name="useEmbeddedDex" />
-        <public name="forceUriPermissions" />
-        <!-- @hide @SystemApi -->
-        <public name="allowClearUserDataOnFailedRestore"/>
-        <public name="allowAudioPlaybackCapture"/>
-        <public name="secureElementName" />
-        <public name="requestLegacyExternalStorage"/>
-        <public name="enforceStatusBarContrast" />
-        <public name="enforceNavigationBarContrast" />
-        <public name="identifier" />
+    <public-group type="attr" first-id="0x01010607">
     </public-group>
 
-    <public-group type="drawable" first-id="0x010800b4">
-        <!-- @hide @SystemApi -->
-        <public name="ic_info" />
+    <public-group type="drawable" first-id="0x010800b5">
     </public-group>
 
-    <public-group type="style" first-id="0x010302e2">
-        <!-- @hide @SystemApi -->
-        <public name="Theme.DeviceDefault.DocumentsUI" />
-        <public name="Theme.DeviceDefault.DayNight" />
-        <public name="ThemeOverlay.DeviceDefault.Accent.DayNight" />
+    <public-group type="style" first-id="0x010302e5">
     </public-group>
 
-    <public-group type="id" first-id="0x01020046">
-      <public name="accessibilityActionPageUp" />
-      <public name="accessibilityActionPageDown" />
-      <public name="accessibilityActionPageLeft" />
-      <public name="accessibilityActionPageRight" />
+    <public-group type="id" first-id="0x0102004a">
     </public-group>
 
-    <public-group type="string" first-id="0x0104001b">
-        <!-- @hide @SystemApi -->
-        <public name="config_helpPackageNameKey" />
-        <!-- @hide @SystemApi -->
-        <public name="config_helpPackageNameValue" />
-        <!-- @hide @SystemApi -->
-        <public name="config_helpIntentExtraKey" />
-        <!-- @hide @SystemApi -->
-        <public name="config_helpIntentNameKey" />
-        <!-- @hide @SystemApi -->
-        <public name="config_feedbackIntentExtraKey" />
-        <!-- @hide @SystemApi -->
-        <public name="config_feedbackIntentNameKey" />
-      <!-- @hide @SystemApi @TestApi -->
-      <public name="config_defaultAssistant" />
-      <!-- @hide @SystemApi -->
-      <public name="config_defaultBrowser" />
-      <!-- @hide @SystemApi @TestApi -->
-      <public name="config_defaultDialer" />
-      <!-- @hide @SystemApi -->
-      <public name="config_defaultSms" />
+    <public-group type="string" first-id="0x01040025">
     </public-group>
 
-    <public-group type="bool" first-id="0x01110000">
-        <!-- @hide @SystemApi -->
-        <public name="config_sendPackageName" />
-      <!-- @hide @SystemApi -->
-      <public name="config_showDefaultAssistant" />
-      <!-- @hide @SystemApi -->
-      <public name="config_showDefaultEmergency" />
-      <!-- @hide @SystemApi -->
-      <public name="config_showDefaultHome" />
-      <!-- @hide @TestApi -->
-      <public name="config_perDisplayFocusEnabled" />
+    <public-group type="bool" first-id="0x01110005">
     </public-group>
 
-    <public-group type="dimen" first-id="0x01050007">
-        <!-- @hide @SystemApi -->
-        <public name="config_restrictedIconSize" />
+    <public-group type="dimen" first-id="0x01050008">
     </public-group>
 
-    <public-group type="color" first-id="0x0106001c">
-        <!-- @hide @SystemApi -->
-        <public name="system_notification_accent_color" />
+    <public-group type="color" first-id="0x0106001d">
     </public-group>
 
   <!-- ===============================================================
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7de6ca5..37678dd 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1561,7 +1561,7 @@
     <!-- Error message shown when the face hardware can't be accessed. [CHAR LIMIT=69] -->
     <string name="face_error_hw_not_available">Can\u2019t verify face. Hardware not available.</string>
     <!-- Error message shown when the face hardware timer has expired and the user needs to restart the operation. [CHAR LIMIT=50] -->
-    <string name="face_error_timeout">Face timeout reached. Try again.</string>
+    <string name="face_error_timeout">Try face authentication again.</string>
     <!-- Error message shown when the face hardware has run out of room for storing faces. [CHAR LIMIT=69] -->
     <string name="face_error_no_space">Can\u2019t store new face data. Delete an old one first.</string>
     <!-- Generic error message shown when the face operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1ef2eb4..3a348f0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2279,6 +2279,8 @@
 
   <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
   <java-symbol type="dimen" name="status_bar_icon_size" />
+  <java-symbol type="dimen" name="status_bar_system_icon_size" />
+  <java-symbol type="dimen" name="status_bar_system_icon_intrinsic_size" />
   <java-symbol type="drawable" name="list_selector_pressed_holo_dark" />
   <java-symbol type="drawable" name="scrubber_control_disabled_holo" />
   <java-symbol type="drawable" name="scrubber_control_selector_holo" />
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8551234..f326ce8 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -153,8 +153,7 @@
         mNativeSurface = nullptr;
     }
 
-    if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f &&
-            !mFixedRenderAhead) {
+    if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f) {
         mFixedRenderAhead = false;
         mRenderAheadCapacity = 1;
     } else {
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
index 360e8d3..60d0318 100644
--- a/libs/protoutil/include/android/util/ProtoOutputStream.h
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -123,6 +123,7 @@
     size_t size(); // Get the size of the serialized protobuf.
     sp<ProtoReader> data(); // Get the reader apis of the data.
     bool flush(int fd); // Flush data directly to a file descriptor.
+    bool serializeToString(std::string* out); // Serializes the proto to a string.
 
     /**
      * Clears the ProtoOutputStream so the buffer can be reused instead of deallocation/allocation again.
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index ccbb83b..98a68c6 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -448,6 +448,23 @@
     return true;
 }
 
+bool
+ProtoOutputStream::serializeToString(std::string* out)
+{
+    if (out == nullptr) return false;
+    if (!compact()) return false;
+
+
+    sp<ProtoReader> reader = mBuffer->read();
+    out->reserve(reader->size());
+    while (reader->hasNext()) {
+        out->append(static_cast<const char*>(static_cast<const void*>(reader->readBuffer())),
+                    reader->currentToRead());
+        reader->move(reader->currentToRead());
+    }
+    return true;
+}
+
 sp<ProtoReader>
 ProtoOutputStream::data()
 {
diff --git a/libs/protoutil/tests/EncodedBuffer_test.cpp b/libs/protoutil/tests/EncodedBuffer_test.cpp
index 398af60..f895154 100644
--- a/libs/protoutil/tests/EncodedBuffer_test.cpp
+++ b/libs/protoutil/tests/EncodedBuffer_test.cpp
@@ -29,101 +29,101 @@
 }
 
 TEST(EncodedBufferTest, WriteSimple) {
-    EncodedBuffer buffer(TEST_CHUNK_SIZE);
-    EXPECT_EQ(buffer.size(), 0UL);
-    expectPointer(buffer.wp(), 0);
-    EXPECT_EQ(buffer.currentToWrite(), TEST_CHUNK_SIZE);
+    sp<EncodedBuffer> buffer = new EncodedBuffer(TEST_CHUNK_SIZE);
+    EXPECT_EQ(buffer->size(), 0UL);
+    expectPointer(buffer->wp(), 0);
+    EXPECT_EQ(buffer->currentToWrite(), TEST_CHUNK_SIZE);
     for (size_t i = 0; i < TEST_CHUNK_HALF_SIZE; i++) {
-        buffer.writeRawByte(50 + i);
+        buffer->writeRawByte(50 + i);
     }
-    EXPECT_EQ(buffer.size(), TEST_CHUNK_HALF_SIZE);
-    expectPointer(buffer.wp(), TEST_CHUNK_HALF_SIZE);
-    EXPECT_EQ(buffer.currentToWrite(), TEST_CHUNK_HALF_SIZE);
+    EXPECT_EQ(buffer->size(), TEST_CHUNK_HALF_SIZE);
+    expectPointer(buffer->wp(), TEST_CHUNK_HALF_SIZE);
+    EXPECT_EQ(buffer->currentToWrite(), TEST_CHUNK_HALF_SIZE);
     for (size_t i = 0; i < TEST_CHUNK_SIZE; i++) {
-        buffer.writeRawByte(80 + i);
+        buffer->writeRawByte(80 + i);
     }
-    EXPECT_EQ(buffer.size(), TEST_CHUNK_SIZE + TEST_CHUNK_HALF_SIZE);
-    expectPointer(buffer.wp(), TEST_CHUNK_SIZE + TEST_CHUNK_HALF_SIZE);
-    EXPECT_EQ(buffer.currentToWrite(), TEST_CHUNK_HALF_SIZE);
+    EXPECT_EQ(buffer->size(), TEST_CHUNK_SIZE + TEST_CHUNK_HALF_SIZE);
+    expectPointer(buffer->wp(), TEST_CHUNK_SIZE + TEST_CHUNK_HALF_SIZE);
+    EXPECT_EQ(buffer->currentToWrite(), TEST_CHUNK_HALF_SIZE);
 
     // verifies the buffer's data
-    expectPointer(buffer.ep(), 0);
+    expectPointer(buffer->ep(), 0);
     for (size_t i = 0; i < TEST_CHUNK_HALF_SIZE; i++) {
-        EXPECT_EQ(buffer.readRawByte(), 50 + i);
+        EXPECT_EQ(buffer->readRawByte(), 50 + i);
     }
     for (size_t i = 0; i < TEST_CHUNK_SIZE; i++) {
-        EXPECT_EQ(buffer.readRawByte(), 80 + i);
+        EXPECT_EQ(buffer->readRawByte(), 80 + i);
     }
 
     // clears the buffer
-    buffer.clear();
-    EXPECT_EQ(buffer.size(), 0UL);
-    expectPointer(buffer.wp(), 0);
+    buffer->clear();
+    EXPECT_EQ(buffer->size(), 0UL);
+    expectPointer(buffer->wp(), 0);
 }
 
 TEST(EncodedBufferTest, WriteVarint) {
-    EncodedBuffer buffer(TEST_CHUNK_SIZE);
+    sp<EncodedBuffer> buffer = new EncodedBuffer(TEST_CHUNK_SIZE);
     size_t expected_buffer_size = 0;
-    EXPECT_EQ(buffer.writeRawVarint32(13), 1);
+    EXPECT_EQ(buffer->writeRawVarint32(13), 1);
     expected_buffer_size += 1;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
-    EXPECT_EQ(buffer.writeRawVarint32(UINT32_C(-1)), 5);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
+    EXPECT_EQ(buffer->writeRawVarint32(UINT32_C(-1)), 5);
     expected_buffer_size += 5;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
 
-    EXPECT_EQ(buffer.writeRawVarint64(200), 2);
+    EXPECT_EQ(buffer->writeRawVarint64(200), 2);
     expected_buffer_size += 2;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
-    EXPECT_EQ(buffer.writeRawVarint64(UINT64_C(-1)), 10);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
+    EXPECT_EQ(buffer->writeRawVarint64(UINT64_C(-1)), 10);
     expected_buffer_size += 10;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
 
-    buffer.writeRawFixed32(UINT32_C(-1));
+    buffer->writeRawFixed32(UINT32_C(-1));
     expected_buffer_size += 4;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
-    buffer.writeRawFixed64(UINT64_C(-1));
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
+    buffer->writeRawFixed64(UINT64_C(-1));
     expected_buffer_size += 8;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
 
-    EXPECT_EQ(buffer.writeHeader(32, 2), 2);
+    EXPECT_EQ(buffer->writeHeader(32, 2), 2);
     expected_buffer_size += 2;
-    EXPECT_EQ(buffer.size(), expected_buffer_size);
+    EXPECT_EQ(buffer->size(), expected_buffer_size);
 
     // verify data are correctly written to the buffer.
-    expectPointer(buffer.ep(), 0);
-    EXPECT_EQ(buffer.readRawVarint(), UINT32_C(13));
-    EXPECT_EQ(buffer.readRawVarint(), UINT32_C(-1));
-    EXPECT_EQ(buffer.readRawVarint(), UINT64_C(200));
-    EXPECT_EQ(buffer.readRawVarint(), UINT64_C(-1));
-    EXPECT_EQ(buffer.readRawFixed32(), UINT32_C(-1));
-    EXPECT_EQ(buffer.readRawFixed64(), UINT64_C(-1));
-    EXPECT_EQ(buffer.readRawVarint(), UINT64_C((32 << 3) + 2));
-    expectPointer(buffer.ep(), expected_buffer_size);
+    expectPointer(buffer->ep(), 0);
+    EXPECT_EQ(buffer->readRawVarint(), UINT32_C(13));
+    EXPECT_EQ(buffer->readRawVarint(), UINT32_C(-1));
+    EXPECT_EQ(buffer->readRawVarint(), UINT64_C(200));
+    EXPECT_EQ(buffer->readRawVarint(), UINT64_C(-1));
+    EXPECT_EQ(buffer->readRawFixed32(), UINT32_C(-1));
+    EXPECT_EQ(buffer->readRawFixed64(), UINT64_C(-1));
+    EXPECT_EQ(buffer->readRawVarint(), UINT64_C((32 << 3) + 2));
+    expectPointer(buffer->ep(), expected_buffer_size);
 }
 
 TEST(EncodedBufferTest, Edit) {
-    EncodedBuffer buffer(TEST_CHUNK_SIZE);
-    buffer.writeRawFixed64(0xdeadbeefdeadbeef);
-    EXPECT_EQ(buffer.readRawFixed64(), UINT64_C(0xdeadbeefdeadbeef));
+    sp<EncodedBuffer> buffer = new EncodedBuffer(TEST_CHUNK_SIZE);
+    buffer->writeRawFixed64(0xdeadbeefdeadbeef);
+    EXPECT_EQ(buffer->readRawFixed64(), UINT64_C(0xdeadbeefdeadbeef));
 
-    buffer.editRawFixed32(4, 0x12345678);
+    buffer->editRawFixed32(4, 0x12345678);
     // fixed 64 is little endian order.
-    buffer.ep()->rewind(); // rewind ep for readRawFixed64 from 0
-    EXPECT_EQ(buffer.readRawFixed64(), UINT64_C(0x12345678deadbeef));
+    buffer->ep()->rewind(); // rewind ep for readRawFixed64 from 0
+    EXPECT_EQ(buffer->readRawFixed64(), UINT64_C(0x12345678deadbeef));
 
-    buffer.wp()->rewind();
-    expectPointer(buffer.wp(), 0);
-    buffer.copy(4, 3);
-    buffer.ep()->rewind(); // rewind ep for readRawFixed64 from 0
-    EXPECT_EQ(buffer.readRawFixed64(), UINT64_C(0x12345678de345678));
+    buffer->wp()->rewind();
+    expectPointer(buffer->wp(), 0);
+    buffer->copy(4, 3);
+    buffer->ep()->rewind(); // rewind ep for readRawFixed64 from 0
+    EXPECT_EQ(buffer->readRawFixed64(), UINT64_C(0x12345678de345678));
 }
 
 TEST(EncodedBufferTest, ReadSimple) {
-    EncodedBuffer buffer(TEST_CHUNK_SIZE);
+    sp<EncodedBuffer> buffer = new EncodedBuffer(TEST_CHUNK_SIZE);
     for (size_t i = 0; i < TEST_CHUNK_3X_SIZE; i++) {
-        buffer.writeRawByte(i);
+        buffer->writeRawByte(i);
     }
-    sp<ProtoReader> reader1 = buffer.read();
+    sp<ProtoReader> reader1 = buffer->read();
     EXPECT_EQ(reader1->size(), TEST_CHUNK_3X_SIZE);
     EXPECT_EQ(reader1->bytesRead(), 0);
 
@@ -132,7 +132,7 @@
     }
     EXPECT_EQ(reader1->bytesRead(), TEST_CHUNK_3X_SIZE);
 
-    sp<ProtoReader> reader2 = buffer.read();
+    sp<ProtoReader> reader2 = buffer->read();
     uint8_t val = 0;
     while (reader2->hasNext()) {
         EXPECT_EQ(reader2->next(), val);
@@ -143,10 +143,10 @@
 }
 
 TEST(EncodedBufferTest, ReadVarint) {
-    EncodedBuffer buffer;
+    sp<EncodedBuffer> buffer = new EncodedBuffer();
     uint64_t val = UINT64_C(1522865904593);
-    size_t len = buffer.writeRawVarint64(val);
-    sp<ProtoReader> reader = buffer.read();
+    size_t len = buffer->writeRawVarint64(val);
+    sp<ProtoReader> reader = buffer->read();
     EXPECT_EQ(reader->size(), len);
     EXPECT_EQ(reader->readRawVarint(), val);
 }
diff --git a/libs/protoutil/tests/ProtoOutputStream_test.cpp b/libs/protoutil/tests/ProtoOutputStream_test.cpp
index 9d357f3..6282fd5 100644
--- a/libs/protoutil/tests/ProtoOutputStream_test.cpp
+++ b/libs/protoutil/tests/ProtoOutputStream_test.cpp
@@ -88,6 +88,50 @@
     EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
 }
 
+TEST(ProtoOutputStreamTest, SerializeToStringPrimitives) {
+    std::string s = "hello";
+    const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
+
+    ProtoOutputStream proto;
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
+
+    PrimitiveProto primitives;
+    std::string serialized;
+    ASSERT_TRUE(proto.serializeToString(&serialized));
+    ASSERT_TRUE(primitives.ParseFromString(serialized));
+    EXPECT_EQ(primitives.val_int32(), 123);
+    EXPECT_EQ(primitives.val_int64(), -1);
+    EXPECT_EQ(primitives.val_float(), -23.5f);
+    EXPECT_EQ(primitives.val_double(), 324.5f);
+    EXPECT_EQ(primitives.val_uint32(), 3424);
+    EXPECT_EQ(primitives.val_uint64(), 57);
+    EXPECT_EQ(primitives.val_fixed32(), -20);
+    EXPECT_EQ(primitives.val_fixed64(), -37);
+    EXPECT_EQ(primitives.val_bool(), true);
+    EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
+    EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
+    EXPECT_EQ(primitives.val_sfixed32(), 63);
+    EXPECT_EQ(primitives.val_sfixed64(), -54);
+    EXPECT_EQ(primitives.val_sint32(), -533);
+    EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
+    EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
+}
+
 TEST(ProtoOutputStreamTest, Complex) {
     std::string name1 = "cat";
     std::string name2 = "dog";
@@ -127,6 +171,47 @@
     EXPECT_THAT(log2.data(), StrEq("food"));
 }
 
+TEST(ProtoOutputStreamTest, SerializeToStringComplex) {
+    std::string name1 = "cat";
+    std::string name2 = "dog";
+    const char data1[6] = { 'f', 'u', 'n', 'n', 'y', '!' };
+    const char data2[4] = { 'f', 'o', 'o', 'd' };
+
+    ProtoOutputStream proto;
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 23));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 101));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, -72));
+    uint64_t token1 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 12));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name1));
+    // specify the length to test the write(id, bytes, length) function.
+    EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data1, 5));
+    proto.end(token1);
+    uint64_t token2 = proto.start(FIELD_TYPE_MESSAGE | ComplexProto::kLogsFieldNumber);
+    EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::Log::kIdFieldNumber, 98));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | ComplexProto::Log::kNameFieldNumber, name2));
+    EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | ComplexProto::Log::kDataFieldNumber, data2, 4));
+    proto.end(token2);
+
+    ComplexProto complex;
+    std::string serialized;
+    ASSERT_TRUE(proto.serializeToString(&serialized));
+    ASSERT_TRUE(complex.ParseFromString(serialized));
+    EXPECT_EQ(complex.ints_size(), 3);
+    EXPECT_EQ(complex.ints(0), 23);
+    EXPECT_EQ(complex.ints(1), 101);
+    EXPECT_EQ(complex.ints(2), -72);
+    EXPECT_EQ(complex.logs_size(), 2);
+    ComplexProto::Log log1 = complex.logs(0);
+    EXPECT_EQ(log1.id(), 12);
+    EXPECT_THAT(log1.name(), StrEq(name1.c_str()));
+    EXPECT_THAT(log1.data(), StrEq("funny")); // should not contain '!'
+    ComplexProto::Log log2 = complex.logs(1);
+    EXPECT_EQ(log2.id(), 98);
+    EXPECT_THAT(log2.name(), StrEq(name2.c_str()));
+    EXPECT_THAT(log2.data(), StrEq("food"));
+}
+
 TEST(ProtoOutputStreamTest, Reusability) {
     ProtoOutputStream proto;
     EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | ComplexProto::kIntsFieldNumber, 32));
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 68c0a22..435d8d7 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -509,35 +509,16 @@
      * @return The position of the {@link Uri}, or -1 if it cannot be found.
      */
     public int getRingtonePosition(Uri ringtoneUri) {
-        
         if (ringtoneUri == null) return -1;
+        final long ringtoneId = ContentUris.parseId(ringtoneUri);
         
         final Cursor cursor = getCursor();
-        final int cursorCount = cursor.getCount();
-        
-        if (!cursor.moveToFirst()) {
-            return -1;
-        }
-        
-        // Only create Uri objects when the actual URI changes
-        Uri currentUri = null;
-        String previousUriString = null;
-        for (int i = 0; i < cursorCount; i++) {
-            String uriString = cursor.getString(URI_COLUMN_INDEX);
-            if (currentUri == null || !uriString.equals(previousUriString)) {
-                currentUri = Uri.parse(uriString);
+        cursor.moveToPosition(-1);
+        while (cursor.moveToNext()) {
+            if (ringtoneId == cursor.getLong(ID_COLUMN_INDEX)) {
+                return cursor.getPosition();
             }
-            
-            if (ringtoneUri.equals(ContentUris.withAppendedId(currentUri, cursor
-                    .getLong(ID_COLUMN_INDEX)))) {
-                return i;
-            }
-            
-            cursor.move(1);
-            
-            previousUriString = uriString;
         }
-        
         return -1;
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index f5dab01..9b6ab06 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -314,6 +314,7 @@
     public void showKeyguard() {
         super.showKeyguard();
         updateNavBarForKeyguardContent();
+        dismissKeyguardWhenUserSwitcherNotDisplayed();
     }
 
     /**
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 43d7d8f..e731b45 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -70,6 +70,10 @@
 
     private static final String TAG = "DynSystemInstallationService";
 
+
+    // TODO (b/131866826): This is currently for test only. Will move this to System API.
+    static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
+
     /*
      * Intent actions
      */
@@ -122,6 +126,9 @@
     private long mInstalledSize;
     private boolean mJustCancelledByUser;
 
+    // This is for testing only now
+    private boolean mEnableWhenCompleted;
+
     private InstallationAsyncTask mInstallTask;
 
 
@@ -178,6 +185,11 @@
     public void onResult(int result, Throwable detail) {
         if (result == RESULT_OK) {
             postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
+
+            // For testing: enable DSU and restart the device when install completed
+            if (mEnableWhenCompleted) {
+                executeRebootToDynSystemCommand();
+            }
             return;
         }
 
@@ -224,6 +236,7 @@
         String url = intent.getDataString();
         mSystemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
         mUserdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
+        mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
 
         mInstallTask = new InstallationAsyncTask(
                 url, mSystemSize, mUserdataSize, this, mDynSystem, this);
@@ -275,7 +288,7 @@
     private void executeRebootToDynSystemCommand() {
         boolean enabled = false;
 
-        if (mInstallTask != null && mInstallTask.getStatus() == FINISHED) {
+        if (mInstallTask != null && mInstallTask.getResult() == RESULT_OK) {
             enabled = mInstallTask.commit();
         } else if (isDynamicSystemInstalled()) {
             enabled = mDynSystem.setEnable(true);
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index b1c09381..8a2948b 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -92,6 +92,8 @@
         Uri url = callingIntent.getData();
         long systemSize = callingIntent.getLongExtra(KEY_SYSTEM_SIZE, 0);
         long userdataSize = callingIntent.getLongExtra(KEY_USERDATA_SIZE, 0);
+        boolean enableWhenCompleted = callingIntent.getBooleanExtra(
+                DynamicSystemInstallationService.KEY_ENABLE_WHEN_COMPLETED, false);
 
         sVerifiedUrl = url.toString();
 
@@ -101,6 +103,8 @@
         intent.setAction(DynamicSystemClient.ACTION_START_INSTALL);
         intent.putExtra(KEY_SYSTEM_SIZE, systemSize);
         intent.putExtra(KEY_USERDATA_SIZE, userdataSize);
+        intent.putExtra(
+                DynamicSystemInstallationService.KEY_ENABLE_WHEN_COMPLETED, enableWhenCompleted);
 
         Log.d(TAG, "Starting Installation Service");
         startServiceAsUser(intent, UserHandle.SYSTEM);
diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
index 359c859..f054319 100644
--- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java
+++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
@@ -155,7 +155,8 @@
         DROPPED_ETHERTYPE_BLACKLISTED,
         DROPPED_ARP_REPLY_SPA_NO_HOST,
         DROPPED_IPV4_KEEPALIVE_ACK,
-        DROPPED_IPV6_KEEPALIVE_ACK;
+        DROPPED_IPV6_KEEPALIVE_ACK,
+        DROPPED_IPV4_NATT_KEEPALIVE;
 
         // Returns the negative byte offset from the end of the APF data segment for
         // a given counter.
@@ -857,12 +858,104 @@
         }
     }
 
-    // A class to hold keepalive ack information.
-    private abstract static class TcpKeepaliveAck {
+    // TODO: Refactor these subclasses to avoid so much repetition.
+    private abstract static class KeepalivePacket {
         // Note that the offset starts from IP header.
         // These must be added ether header length when generating program.
         static final int IP_HEADER_OFFSET = 0;
+        static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12;
 
+        // Append a filter for this keepalive ack to {@code gen}.
+        // Jump to drop if it matches the keepalive ack.
+        // Jump to the next filter if packet doesn't match the keepalive ack.
+        abstract void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException;
+    }
+
+    // A class to hold NAT-T keepalive ack information.
+    private class NattKeepaliveResponse extends KeepalivePacket {
+        static final int UDP_LENGTH_OFFSET = 4;
+        static final int UDP_HEADER_LEN = 8;
+
+        protected class NattKeepaliveResponseData {
+            public final byte[] srcAddress;
+            public final int srcPort;
+            public final byte[] dstAddress;
+            public final int dstPort;
+
+            NattKeepaliveResponseData(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
+                srcAddress = sentKeepalivePacket.dstAddress;
+                srcPort = sentKeepalivePacket.dstPort;
+                dstAddress = sentKeepalivePacket.srcAddress;
+                dstPort = sentKeepalivePacket.srcPort;
+            }
+        }
+
+        protected final NattKeepaliveResponseData mPacket;
+        protected final byte[] mSrcDstAddr;
+        protected final byte[] mPortFingerprint;
+        // NAT-T keepalive packet
+        protected final byte[] mPayload = {(byte) 0xff};
+
+        NattKeepaliveResponse(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
+            mPacket = new NattKeepaliveResponseData(sentKeepalivePacket);
+            mSrcDstAddr = concatArrays(mPacket.srcAddress, mPacket.dstAddress);
+            mPortFingerprint = generatePortFingerprint(mPacket.srcPort, mPacket.dstPort);
+        }
+
+        byte[] generatePortFingerprint(int srcPort, int dstPort) {
+            final ByteBuffer fp = ByteBuffer.allocate(4);
+            fp.order(ByteOrder.BIG_ENDIAN);
+            fp.putShort((short) srcPort);
+            fp.putShort((short) dstPort);
+            return fp.array();
+        }
+
+        @Override
+        void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
+            final String nextFilterLabel = "natt_keepalive_filter" + getUniqueNumberLocked();
+
+            gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN + IPV4_SRC_ADDR_OFFSET);
+            gen.addJumpIfBytesNotEqual(Register.R0, mSrcDstAddr, nextFilterLabel);
+
+            // A NAT-T keepalive packet contains 1 byte payload with the value 0xff
+            // Check payload length is 1
+            gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addAdd(UDP_HEADER_LEN);
+            gen.addSwap();
+            gen.addLoad16(Register.R0, IPV4_TOTAL_LENGTH_OFFSET);
+            gen.addNeg(Register.R1);
+            gen.addAddR1();
+            gen.addJumpIfR0NotEquals(1, nextFilterLabel);
+
+            // Check that the ports match
+            gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addAdd(ETH_HEADER_LEN);
+            gen.addJumpIfBytesNotEqual(Register.R0, mPortFingerprint, nextFilterLabel);
+
+            // Payload offset = R0 + UDP header length
+            gen.addAdd(UDP_HEADER_LEN);
+            gen.addJumpIfBytesNotEqual(Register.R0, mPayload, nextFilterLabel);
+
+            maybeSetupCounter(gen, Counter.DROPPED_IPV4_NATT_KEEPALIVE);
+            gen.addJump(mCountAndDropLabel);
+            gen.defineLabel(nextFilterLabel);
+        }
+
+        public String toString() {
+            try {
+                return String.format("%s -> %s",
+                        NetworkStackUtils.addressAndPortToString(
+                                InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort),
+                        NetworkStackUtils.addressAndPortToString(
+                                InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort));
+            } catch (UnknownHostException e) {
+                return "Unknown host";
+            }
+        }
+    }
+
+    // A class to hold TCP keepalive ack information.
+    private abstract static class TcpKeepaliveAck extends KeepalivePacket {
         protected static class TcpKeepaliveAckData {
             public final byte[] srcAddress;
             public final int srcPort;
@@ -870,6 +963,7 @@
             public final int dstPort;
             public final int seq;
             public final int ack;
+
             // Create the characteristics of the ack packet from the sent keepalive packet.
             TcpKeepaliveAckData(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
                 srcAddress = sentKeepalivePacket.dstAddress;
@@ -902,28 +996,18 @@
             return fp.array();
         }
 
-        static byte[] concatArrays(final byte[]... arr) {
-            int size = 0;
-            for (byte[] a : arr) {
-                size += a.length;
-            }
-            final byte[] result = new byte[size];
-            int offset = 0;
-            for (byte[] a : arr) {
-                System.arraycopy(a, 0, result, offset, a.length);
-                offset += a.length;
-            }
-            return result;
-        }
-
         public String toString() {
-            return String.format("%s(%d) -> %s(%d), seq=%d, ack=%d",
-                    mPacket.srcAddress,
-                    mPacket.srcPort,
-                    mPacket.dstAddress,
-                    mPacket.dstPort,
-                    mPacket.seq,
-                    mPacket.ack);
+            try {
+                return String.format("%s -> %s , seq=%d, ack=%d",
+                        NetworkStackUtils.addressAndPortToString(
+                                InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort),
+                        NetworkStackUtils.addressAndPortToString(
+                                InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort),
+                        Integer.toUnsignedLong(mPacket.seq),
+                        Integer.toUnsignedLong(mPacket.ack));
+            } catch (UnknownHostException e) {
+                return "Unknown host";
+            }
         }
 
         // Append a filter for this keepalive ack to {@code gen}.
@@ -933,7 +1017,6 @@
     }
 
     private class TcpKeepaliveAckV4 extends TcpKeepaliveAck {
-        private static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12;
 
         TcpKeepaliveAckV4(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
             this(new TcpKeepaliveAckData(sentKeepalivePacket));
@@ -987,7 +1070,7 @@
 
         @Override
         void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
-            throw new UnsupportedOperationException("IPv6 Keepalive is not supported yet");
+            throw new UnsupportedOperationException("IPv6 TCP Keepalive is not supported yet");
         }
     }
 
@@ -997,7 +1080,7 @@
     @GuardedBy("this")
     private ArrayList<Ra> mRas = new ArrayList<>();
     @GuardedBy("this")
-    private SparseArray<TcpKeepaliveAck> mKeepaliveAcks = new SparseArray<>();
+    private SparseArray<KeepalivePacket> mKeepalivePackets = new SparseArray<>();
 
     // There is always some marginal benefit to updating the installed APF program when an RA is
     // seen because we can extend the program's lifetime slightly, but there is some cost to
@@ -1171,9 +1254,12 @@
                 gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel);
             }
 
-            // If any keepalive filter matches, drop
+            // If any TCP keepalive filter matches, drop
             generateV4KeepaliveFilters(gen);
 
+            // If any NAT-T keepalive filter matches, drop
+            generateV4NattKeepaliveFilters(gen);
+
             // Otherwise, this is an IPv4 unicast, pass
             // If L2 broadcast packet, drop.
             // TODO: can we invert this condition to fall through to the common pass case below?
@@ -1184,6 +1270,7 @@
             gen.addJump(mCountAndDropLabel);
         } else {
             generateV4KeepaliveFilters(gen);
+            generateV4NattKeepaliveFilters(gen);
         }
 
         // Otherwise, pass
@@ -1191,25 +1278,36 @@
         gen.addJump(mCountAndPassLabel);
     }
 
-    private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
-        final String skipV4KeepaliveFilter = "skip_v4_keepalive_filter";
-        final boolean haveV4KeepaliveAcks = NetworkStackUtils.any(mKeepaliveAcks,
-                ack -> ack instanceof TcpKeepaliveAckV4);
+    private void generateKeepaliveFilters(ApfGenerator gen, Class<?> filterType, int proto,
+            int offset, String label) throws IllegalInstructionException {
+        final boolean haveKeepaliveResponses = NetworkStackUtils.any(mKeepalivePackets,
+                ack -> filterType.isInstance(ack));
 
-        // If no keepalive acks
-        if (!haveV4KeepaliveAcks) return;
+        // If no keepalive packets of this type
+        if (!haveKeepaliveResponses) return;
 
-        // If not tcp, skip keepalive filters
-        gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
-        gen.addJumpIfR0NotEquals(IPPROTO_TCP, skipV4KeepaliveFilter);
+        // If not the right proto, skip keepalive filters
+        gen.addLoad8(Register.R0, offset);
+        gen.addJumpIfR0NotEquals(proto, label);
 
-        // Drop IPv4 Keepalive acks
-        for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
-            final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i);
-            if (ack instanceof TcpKeepaliveAckV4) ack.generateFilterLocked(gen);
+        // Drop Keepalive responses
+        for (int i = 0; i < mKeepalivePackets.size(); ++i) {
+            final KeepalivePacket response = mKeepalivePackets.valueAt(i);
+            if (filterType.isInstance(response)) response.generateFilterLocked(gen);
         }
 
-        gen.defineLabel(skipV4KeepaliveFilter);
+        gen.defineLabel(label);
+    }
+
+    private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
+        generateKeepaliveFilters(gen, TcpKeepaliveAckV4.class, IPPROTO_TCP, IPV4_PROTOCOL_OFFSET,
+                "skip_v4_keepalive_filter");
+    }
+
+    private void generateV4NattKeepaliveFilters(ApfGenerator gen)
+            throws IllegalInstructionException {
+        generateKeepaliveFilters(gen, NattKeepaliveResponse.class,
+                IPPROTO_UDP, IPV4_PROTOCOL_OFFSET, "skip_v4_nattkeepalive_filter");
     }
 
     /**
@@ -1294,24 +1392,8 @@
     }
 
     private void generateV6KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
-        final String skipV6KeepaliveFilter = "skip_v6_keepalive_filter";
-        final boolean haveV6KeepaliveAcks = NetworkStackUtils.any(mKeepaliveAcks,
-                ack -> ack instanceof TcpKeepaliveAckV6);
-
-        // If no keepalive acks
-        if (!haveV6KeepaliveAcks) return;
-
-        // If not tcp, skip keepalive filters
-        gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET);
-        gen.addJumpIfR0NotEquals(IPPROTO_TCP, skipV6KeepaliveFilter);
-
-        // Drop IPv6 Keepalive acks
-        for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
-            final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i);
-            if (ack instanceof TcpKeepaliveAckV6) ack.generateFilterLocked(gen);
-        }
-
-        gen.defineLabel(skipV6KeepaliveFilter);
+        generateKeepaliveFilters(gen, TcpKeepaliveAckV6.class, IPPROTO_TCP, IPV6_NEXT_HEADER_OFFSET,
+                "skip_v6_keepalive_filter");
     }
 
     /**
@@ -1701,26 +1783,34 @@
     public synchronized void addTcpKeepalivePacketFilter(final int slot,
             final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
         log("Adding keepalive ack(" + slot + ")");
-        if (null != mKeepaliveAcks.get(slot)) {
+        if (null != mKeepalivePackets.get(slot)) {
             throw new IllegalArgumentException("Keepalive slot " + slot + " is occupied");
         }
         final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6;
-        mKeepaliveAcks.put(slot, (ipVersion == 4)
+        mKeepalivePackets.put(slot, (ipVersion == 4)
                 ? new TcpKeepaliveAckV4(sentKeepalivePacket)
                 : new TcpKeepaliveAckV6(sentKeepalivePacket));
         installNewProgramLocked();
     }
 
     /**
-     * Add NATT keepalive packet filter.
-     * This will add a filter to drop NATT keepalive packet which is passed as an argument.
+     * Add NAT-T keepalive packet filter.
+     * This will add a filter to drop NAT-T keepalive packet which is passed as an argument.
      *
      * @param slot The index used to access the filter.
      * @param sentKeepalivePacket The attributes of the sent keepalive packet.
      */
     public synchronized void addNattKeepalivePacketFilter(final int slot,
             final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
-        Log.e(TAG, "APF add NATT keepalive filter is not implemented");
+        log("Adding NAT-T keepalive packet(" + slot + ")");
+        if (null != mKeepalivePackets.get(slot)) {
+            throw new IllegalArgumentException("NAT-T Keepalive slot " + slot + " is occupied");
+        }
+        if (sentKeepalivePacket.srcAddress.length != 4) {
+            throw new IllegalArgumentException("NAT-T keepalive is only supported on IPv4");
+        }
+        mKeepalivePackets.put(slot, new NattKeepaliveResponse(sentKeepalivePacket));
+        installNewProgramLocked();
     }
 
     /**
@@ -1729,7 +1819,8 @@
      * @param slot The index used to access the filter.
      */
     public synchronized void removeKeepalivePacketFilter(int slot) {
-        mKeepaliveAcks.remove(slot);
+        log("Removing keepalive packet(" + slot + ")");
+        mKeepalivePackets.remove(slot);
         installNewProgramLocked();
     }
 
@@ -1785,14 +1876,29 @@
         }
         pw.decreaseIndent();
 
-        pw.println("Keepalive filters:");
+        pw.println("TCP Keepalive filters:");
         pw.increaseIndent();
-        for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
-            final TcpKeepaliveAck keepaliveAck = mKeepaliveAcks.valueAt(i);
-            pw.print("Slot ");
-            pw.print(mKeepaliveAcks.keyAt(i));
-            pw.print(" : ");
-            pw.println(keepaliveAck);
+        for (int i = 0; i < mKeepalivePackets.size(); ++i) {
+            final KeepalivePacket keepalivePacket = mKeepalivePackets.valueAt(i);
+            if (keepalivePacket instanceof TcpKeepaliveAck) {
+                pw.print("Slot ");
+                pw.print(mKeepalivePackets.keyAt(i));
+                pw.print(": ");
+                pw.println(keepalivePacket);
+            }
+        }
+        pw.decreaseIndent();
+
+        pw.println("NAT-T Keepalive filters:");
+        pw.increaseIndent();
+        for (int i = 0; i < mKeepalivePackets.size(); ++i) {
+            final KeepalivePacket keepalivePacket = mKeepalivePackets.valueAt(i);
+            if (keepalivePacket instanceof NattKeepaliveResponse) {
+                pw.print("Slot ");
+                pw.print(mKeepalivePackets.keyAt(i));
+                pw.print(": ");
+                pw.println(keepalivePacket);
+            }
         }
         pw.decreaseIndent();
 
@@ -1858,4 +1964,18 @@
                 + (uint8(bytes[2]) << 8)
                 + (uint8(bytes[3]));
     }
+
+    private static byte[] concatArrays(final byte[]... arr) {
+        int size = 0;
+        for (byte[] a : arr) {
+            size += a.length;
+        }
+        final byte[] result = new byte[size];
+        int offset = 0;
+        for (byte[] a : arr) {
+            System.arraycopy(a, 0, result, offset, a.length);
+            offset += a.length;
+        }
+        return result;
+    }
 }
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index 2934e1c..9bf1b96 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -24,6 +24,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.net.SocketException;
 import java.util.List;
 import java.util.function.Predicate;
@@ -228,4 +230,13 @@
 
     private static native void addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname,
             FileDescriptor fd) throws IOException;
+
+    /**
+     * Return IP address and port in a string format.
+     */
+    public static String addressAndPortToString(InetAddress address, int port) {
+        return String.format(
+                (address instanceof Inet6Address) ? "[%s]:%d" : "%s:%d",
+                        address.getHostAddress(), port);
+    }
 }
diff --git a/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java
index 85f94e1..4767d55 100644
--- a/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java
+++ b/packages/NetworkStack/src/com/android/networkstack/util/DnsUtils.java
@@ -55,12 +55,23 @@
             throws UnknownHostException {
         final List<InetAddress> result = new ArrayList<InetAddress>();
 
-        result.addAll(Arrays.asList(
-                getAllByName(dnsResolver, network, host, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
-                timeout)));
-        result.addAll(Arrays.asList(
-                getAllByName(dnsResolver, network, host, TYPE_A, FLAG_NO_CACHE_LOOKUP,
-                timeout)));
+        try {
+            result.addAll(Arrays.asList(
+                    getAllByName(dnsResolver, network, host, TYPE_AAAA, FLAG_NO_CACHE_LOOKUP,
+                    timeout)));
+        } catch (UnknownHostException e) {
+            // Might happen if the host is v4-only, still need to query TYPE_A
+        }
+        try {
+            result.addAll(Arrays.asList(
+                    getAllByName(dnsResolver, network, host, TYPE_A, FLAG_NO_CACHE_LOOKUP,
+                    timeout)));
+        } catch (UnknownHostException e) {
+            // Might happen if the host is v6-only, still need to return AAAA answers
+        }
+        if (result.size() == 0) {
+            throw new UnknownHostException(host);
+        }
         return result.toArray(new InetAddress[0]);
     }
 
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index 93ab3be..8f2b968 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -40,6 +40,7 @@
 import android.content.Context;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.NattKeepalivePacketDataParcelable;
 import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.apf.ApfFilter.ApfConfiguration;
 import android.net.apf.ApfGenerator.IllegalInstructionException;
@@ -998,47 +999,54 @@
         }
     }
 
-    private static final int ETH_HEADER_LEN = 14;
-    private static final int ETH_DEST_ADDR_OFFSET = 0;
-    private static final int ETH_ETHERTYPE_OFFSET = 12;
+    private static final int ETH_HEADER_LEN               = 14;
+    private static final int ETH_DEST_ADDR_OFFSET         = 0;
+    private static final int ETH_ETHERTYPE_OFFSET         = 12;
     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
 
-    private static final int IPV4_HEADER_LEN = 20;
-    private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
+    private static final int IPV4_HEADER_LEN          = 20;
+    private static final int IPV4_VERSION_IHL_OFFSET  = ETH_HEADER_LEN + 0;
     private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2;
-    private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
-    private static final int IPV4_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 12;
-    private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
-    private static final int IPV4_TCP_HEADER_LEN = 20;
-    private static final int IPV4_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV4_HEADER_LEN;
-    private static final int IPV4_TCP_SRC_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 0;
-    private static final int IPV4_TCP_DEST_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 2;
-    private static final int IPV4_TCP_SEQ_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 4;
-    private static final int IPV4_TCP_ACK_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 8;
+    private static final int IPV4_PROTOCOL_OFFSET     = ETH_HEADER_LEN + 9;
+    private static final int IPV4_SRC_ADDR_OFFSET     = ETH_HEADER_LEN + 12;
+    private static final int IPV4_DEST_ADDR_OFFSET    = ETH_HEADER_LEN + 16;
+
+    private static final int IPV4_TCP_HEADER_LEN           = 20;
+    private static final int IPV4_TCP_HEADER_OFFSET        = ETH_HEADER_LEN + IPV4_HEADER_LEN;
+    private static final int IPV4_TCP_SRC_PORT_OFFSET      = IPV4_TCP_HEADER_OFFSET + 0;
+    private static final int IPV4_TCP_DEST_PORT_OFFSET     = IPV4_TCP_HEADER_OFFSET + 2;
+    private static final int IPV4_TCP_SEQ_NUM_OFFSET       = IPV4_TCP_HEADER_OFFSET + 4;
+    private static final int IPV4_TCP_ACK_NUM_OFFSET       = IPV4_TCP_HEADER_OFFSET + 8;
     private static final int IPV4_TCP_HEADER_LENGTH_OFFSET = IPV4_TCP_HEADER_OFFSET + 12;
-    private static final int IPV4_TCP_HEADER_FLAG_OFFSET = IPV4_TCP_HEADER_OFFSET + 13;
+    private static final int IPV4_TCP_HEADER_FLAG_OFFSET   = IPV4_TCP_HEADER_OFFSET + 13;
+
+    private static final int IPV4_UDP_HEADER_OFFSET    = ETH_HEADER_LEN + IPV4_HEADER_LEN;;
+    private static final int IPV4_UDP_SRC_PORT_OFFSET  = IPV4_UDP_HEADER_OFFSET + 0;
+    private static final int IPV4_UDP_DEST_PORT_OFFSET = IPV4_UDP_HEADER_OFFSET + 2;
+    private static final int IPV4_UDP_LENGTH_OFFSET    = IPV4_UDP_HEADER_OFFSET + 4;
+    private static final int IPV4_UDP_PAYLOAD_OFFSET   = IPV4_UDP_HEADER_OFFSET + 8;
     private static final byte[] IPV4_BROADCAST_ADDRESS =
             {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
 
-    private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
-    private static final int IPV6_HEADER_LEN = 40;
-    private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
-    private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
-    private static final int IPV6_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
-    private static final int IPV6_TCP_SRC_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 0;
-    private static final int IPV6_TCP_DEST_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 2;
-    private static final int IPV6_TCP_SEQ_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 4;
-    private static final int IPV6_TCP_ACK_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 8;
+    private static final int IPV6_HEADER_LEN             = 40;
+    private static final int IPV6_NEXT_HEADER_OFFSET     = ETH_HEADER_LEN + 6;
+    private static final int IPV6_SRC_ADDR_OFFSET        = ETH_HEADER_LEN + 8;
+    private static final int IPV6_DEST_ADDR_OFFSET       = ETH_HEADER_LEN + 24;
+    private static final int IPV6_TCP_HEADER_OFFSET      = ETH_HEADER_LEN + IPV6_HEADER_LEN;
+    private static final int IPV6_TCP_SRC_PORT_OFFSET    = IPV6_TCP_HEADER_OFFSET + 0;
+    private static final int IPV6_TCP_DEST_PORT_OFFSET   = IPV6_TCP_HEADER_OFFSET + 2;
+    private static final int IPV6_TCP_SEQ_NUM_OFFSET     = IPV6_TCP_HEADER_OFFSET + 4;
+    private static final int IPV6_TCP_ACK_NUM_OFFSET     = IPV6_TCP_HEADER_OFFSET + 8;
     // The IPv6 all nodes address ff02::1
-    private static final byte[] IPV6_ALL_NODES_ADDRESS =
+    private static final byte[] IPV6_ALL_NODES_ADDRESS   =
             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
     private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
             { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
 
-    private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
-    private static final int ICMP6_ROUTER_SOLICITATION = 133;
-    private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
+    private static final int ICMP6_TYPE_OFFSET           = ETH_HEADER_LEN + IPV6_HEADER_LEN;
+    private static final int ICMP6_ROUTER_SOLICITATION   = 133;
+    private static final int ICMP6_ROUTER_ADVERTISEMENT  = 134;
     private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
     private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
 
@@ -1050,9 +1058,9 @@
     private static final int ICMP6_RA_OPTION_OFFSET =
             ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
 
-    private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
-    private static final int ICMP6_PREFIX_OPTION_LEN = 32;
-    private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
+    private static final int ICMP6_PREFIX_OPTION_TYPE                      = 3;
+    private static final int ICMP6_PREFIX_OPTION_LEN                       = 32;
+    private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET     = 4;
     private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
 
     // From RFC6106: Recursive DNS Server option
@@ -1063,17 +1071,17 @@
     // From RFC4191: Route Information option
     private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
     // Above three options all have the same format:
-    private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
+    private static final int ICMP6_4_BYTE_OPTION_LEN      = 8;
     private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
-    private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+    private static final int ICMP6_4_BYTE_LIFETIME_LEN    = 4;
 
-    private static final int UDP_HEADER_LEN = 8;
+    private static final int UDP_HEADER_LEN              = 8;
     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
 
-    private static final int DHCP_CLIENT_PORT = 68;
+    private static final int DHCP_CLIENT_PORT       = 68;
     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
 
-    private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
+    private static final int ARP_HEADER_OFFSET          = ETH_HEADER_LEN;
     private static final byte[] ARP_IPV4_REQUEST_HEADER = {
             0, 1, // Hardware type: Ethernet (1)
             8, 0, // Protocol type: IP (0x0800)
@@ -1714,6 +1722,83 @@
         return packet.array();
     }
 
+    @Test
+    public void testApfFilterNattKeepalivePacket() throws Exception {
+        final MockIpClientCallback cb = new MockIpClientCallback();
+        final ApfConfiguration config = getDefaultConfig();
+        config.multicastFilter = DROP_MULTICAST;
+        config.ieee802_3Filter = DROP_802_3_FRAMES;
+        final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
+        byte[] program;
+        final int srcPort = 1024;
+        final int dstPort = 4500;
+        final int slot1 = 1;
+        // NAT-T keepalive
+        final byte[] kaPayload = {(byte) 0xff};
+        final byte[] nonKaPayload = {(byte) 0xfe};
+
+        // src: 10.0.0.5, port: 1024
+        // dst: 10.0.0.6, port: 4500
+        InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
+        InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
+
+        final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+        parcel.srcAddress = srcAddr.getAddress();
+        parcel.srcPort = srcPort;
+        parcel.dstAddress = dstAddr.getAddress();
+        parcel.dstPort = dstPort;
+
+        apfFilter.addNattKeepalivePacketFilter(slot1, parcel);
+        program = cb.getApfProgram();
+
+        // Verify IPv4 keepalive packet is dropped
+        // src: 10.0.0.6, port: 4500
+        // dst: 10.0.0.5, port: 1024
+        byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR,
+                    IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */);
+        System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length);
+        assertDrop(program, pkt);
+
+        // Verify a packet with payload length 1 byte but it is not 0xff will pass the filter.
+        System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length);
+        assertPass(program, pkt);
+
+        // Verify IPv4 non-keepalive response packet from the same source address is passed
+        assertPass(program,
+                ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
+                        dstPort, srcPort, 10 /* dataLength */));
+
+        // Verify IPv4 non-keepalive response packet from other source address is passed
+        assertPass(program,
+                ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
+                        dstPort, srcPort, 10 /* dataLength */));
+
+        apfFilter.removeKeepalivePacketFilter(slot1);
+        apfFilter.shutdown();
+    }
+
+    private static byte[] ipv4UdpPacket(byte[] sip, byte[] dip, int sport,
+            int dport, int dataLength) {
+        final int totalLength = dataLength + IPV4_HEADER_LEN + UDP_HEADER_LEN;
+        final int udpLength = UDP_HEADER_LEN + dataLength;
+        ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
+
+        // ether type
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
+
+        // IPv4 header
+        packet.put(IPV4_VERSION_IHL_OFFSET, (byte) 0x45);
+        packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
+        packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_UDP);
+        put(packet, IPV4_SRC_ADDR_OFFSET, sip);
+        put(packet, IPV4_DEST_ADDR_OFFSET, dip);
+        packet.putShort(IPV4_UDP_SRC_PORT_OFFSET, (short) sport);
+        packet.putShort(IPV4_UDP_DEST_PORT_OFFSET, (short) dport);
+        packet.putShort(IPV4_UDP_LENGTH_OFFSET, (short) udpLength);
+
+        return packet.array();
+    }
+
     // Verify that the last program pushed to the IpClient.Callback properly filters the
     // given packet for the given lifetime.
     private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index abfb9c8..2618675 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -297,9 +297,10 @@
         setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
         setFallbackSpecs(null); // Test with no fallback spec by default
         when(mRandom.nextInt()).thenReturn(0);
-
+        // DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise,
+        // it will fail the test because of timeout expired for querying AAAA and A sequentially.
         when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
-                .thenReturn(500);
+                .thenReturn(200);
 
         doAnswer((invocation) -> {
             URL url = invocation.getArgument(0);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 1d351a5..9a95288 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -826,11 +826,22 @@
     }
 
     /**
-     * @return resource for string that discribes the connection state of this device.
-     * case 1: idle or playing media, show "Active" on the only one A2DP active device.
-     * case 2: in phone call, show "Active" on the only one HFP active device
+     * Return full summary that describes connection state of this device
+     *
+     * @see #getConnectionSummary(boolean shortSummary)
      */
     public String getConnectionSummary() {
+        return getConnectionSummary(false /* shortSummary */);
+    }
+
+    /**
+     * Return summary that describes connection state of this device. Summary depends on:
+     * 1. Whether device has battery info
+     * 2. Whether device is in active usage(or in phone call)
+     *
+     * @param shortSummary {@code true} if need to return short version summary
+     */
+    public String getConnectionSummary(boolean shortSummary) {
         boolean profileConnected = false;    // Updated as long as BluetoothProfile is connected
         boolean a2dpConnected = true;        // A2DP is connected
         boolean hfpConnected = true;         // HFP is connected
@@ -909,9 +920,9 @@
                 if ((mIsActiveDeviceHearingAid)
                         || (mIsActiveDeviceHeadset && isOnCall)
                         || (mIsActiveDeviceA2dp && !isOnCall)) {
-                    if (isTwsBatteryAvailable(leftBattery, rightBattery)) {
+                    if (isTwsBatteryAvailable(leftBattery, rightBattery) && !shortSummary) {
                         stringRes = R.string.bluetooth_active_battery_level_untethered;
-                    } else if (batteryLevelPercentageString != null) {
+                    } else if (batteryLevelPercentageString != null && !shortSummary) {
                         stringRes = R.string.bluetooth_active_battery_level;
                     } else {
                         stringRes = R.string.bluetooth_active_no_battery_level;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index c0a1f11..93dcbfe 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -192,6 +192,27 @@
     }
 
     @Test
+    public void getConnectionSummary_shortSummary_returnShortSummary() {
+        // Test without battery level
+        // Set A2DP profile to be connected and test connection state summary
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isNull();
+
+        // Set device as Active for A2DP and test connection state summary
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+        assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isEqualTo("Active");
+
+        // Test with battery level
+        mBatteryLevel = 10;
+        assertThat(mCachedDevice.getConnectionSummary(true /* shortSummary */)).isEqualTo(
+                "Active");
+
+        // Set A2DP profile to be disconnected and test connection state summary
+        updateProfileStatus(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mCachedDevice.getConnectionSummary()).isNull();
+    }
+
+    @Test
     public void getConnectionSummary_testA2dpBatteryInactive_returnBattery() {
         // Arrange:
         //   1. Profile:       {A2DP, CONNECTED, Inactive}
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
index 511910e..4619430 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -5,19 +5,20 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:clipToPadding="false"
     android:theme="@style/qs_theme"
-    android:paddingLeft="@dimen/global_actions_top_padding"
-    android:gravity="right"
+    android:gravity="right | center_vertical"
     android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingRight="@dimen/global_actions_grid_container_shadow_offset"
+    android:layout_marginRight="@dimen/global_actions_grid_container_negative_shadow_offset"
 >
     <LinearLayout
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:gravity="top|right"
-        android:padding="0dp"
         android:orientation="vertical"
         android:layout_marginRight="@dimen/global_actions_grid_container_bottom_margin"
+        android:clipChildren="false"
+        android:clipToPadding="false"
     >
         <!-- Grid of action items -->
         <com.android.systemui.globalactions.ListGridLayout
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
index ff2a7d8..4ece03b 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -5,18 +5,20 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:clipToPadding="false"
     android:theme="@style/qs_theme"
-    android:gravity="left"
-    android:paddingRight="@dimen/global_actions_top_padding"
+    android:gravity="left | center_vertical"
     android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingLeft="@dimen/global_actions_grid_container_shadow_offset"
+    android:layout_marginLeft="@dimen/global_actions_grid_container_negative_shadow_offset"
 >
     <LinearLayout
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:gravity="bottom|left"
         android:padding="0dp"
         android:orientation="vertical"
+        android:clipChildren="false"
+        android:clipToPadding="false"
         android:layout_marginLeft="@dimen/global_actions_grid_container_bottom_margin"
     >
         <!-- For separated items-->
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index 3f10b38..3928062 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -5,17 +5,19 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:clipToPadding="false"
     android:theme="@style/qs_theme"
-    android:gravity="bottom"
+    android:gravity="bottom | center_horizontal"
     android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
+    android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset"
 >
     <LinearLayout
         android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:gravity="bottom | right"
-        android:padding="0dp"
+        android:layout_width="wrap_content"
         android:layoutDirection="ltr"
+        android:clipChildren="false"
+        android:clipToPadding="false"
         android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
     >
         <!-- For separated items-->
diff --git a/packages/SystemUI/res/values-sw320dp/dimens.xml b/packages/SystemUI/res/values-sw320dp/dimens.xml
index 8f27f45..4390d35 100644
--- a/packages/SystemUI/res/values-sw320dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw320dp/dimens.xml
@@ -16,8 +16,6 @@
   -->
 <resources>
     <!-- Global actions grid -->
-    <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen>
-
     <dimen name="global_actions_grid_vertical_padding">0dp</dimen>
     <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
 
diff --git a/packages/SystemUI/res/values-sw392dp/dimens.xml b/packages/SystemUI/res/values-sw392dp/dimens.xml
index 6fa6692..2557ff4 100644
--- a/packages/SystemUI/res/values-sw392dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw392dp/dimens.xml
@@ -16,8 +16,6 @@
   -->
 <resources>
     <!-- Global actions grid -->
-    <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen>
-
     <dimen name="global_actions_grid_vertical_padding">0dp</dimen>
     <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
 
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
index fea1ef1..6780dca 100644
--- a/packages/SystemUI/res/values-sw410dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -23,8 +23,6 @@
     <dimen name="qs_detail_items_padding_top">16dp</dimen>
 
     <!-- Global actions grid -->
-    <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen>
-
     <dimen name="global_actions_grid_vertical_padding">8dp</dimen>
     <dimen name="global_actions_grid_horizontal_padding">4dp</dimen>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6297423..e00e5f2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -41,10 +41,10 @@
 
     <!-- Size of the nav bar edge panels, should be greater to the
          edge sensitivity + the drag threshold -->
-    <dimen name="navigation_edge_panel_width">76dp</dimen>
+    <dimen name="navigation_edge_panel_width">70dp</dimen>
     <!-- Padding at the end of the navigation panel to allow the arrow not to be clipped off -->
-    <dimen name="navigation_edge_panel_padding">24dp</dimen>
-    <dimen name="navigation_edge_panel_height">84dp</dimen>
+    <dimen name="navigation_edge_panel_padding">8dp</dimen>
+    <dimen name="navigation_edge_panel_height">96dp</dimen>
     <!-- The threshold to drag to trigger the edge action -->
     <dimen name="navigation_edge_action_drag_threshold">16dp</dimen>
     <!-- The minimum display position of the arrow on the screen -->
@@ -89,7 +89,7 @@
     <dimen name="status_bar_wifi_signal_spacer_width">2.5dp</dimen>
 
     <!-- Size of the view displaying the wifi signal icon in the status bar. -->
-    <dimen name="status_bar_wifi_signal_size">15dp</dimen>
+    <dimen name="status_bar_wifi_signal_size">@*android:dimen/status_bar_system_icon_size</dimen>
 
     <!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
     <dimen name="status_bar_airplane_spacer_width">4dp</dimen>
@@ -944,6 +944,12 @@
 
     <!-- Global actions grid layout -->
     <dimen name="global_actions_grid_side_margin">4dp</dimen>
+    <dimen name="global_actions_grid_container_bottom_margin">4dp</dimen>
+
+    <!-- Used to workaround a bug where shadows are clipped during animations by expanding
+         the bounds of the parent view. -->
+    <dimen name="global_actions_grid_container_shadow_offset">20dp</dimen>
+    <dimen name="global_actions_grid_container_negative_shadow_offset">-20dp</dimen>
 
     <!-- The maximum offset in either direction that elements are moved horizontally to prevent
          burn-in on AOD. -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 55499da..0e91e41 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -68,6 +68,9 @@
     private final AppearAnimationUtils mAppearAnimationUtils;
     private final DisappearAnimationUtils mDisappearAnimationUtils;
     private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
+    private final int[] mTmpPosition = new int[2];
+    private final Rect mTempRect = new Rect();
+    private final Rect mLockPatternScreenBounds = new Rect();
 
     private CountDownTimer mCountdownTimer = null;
     private LockPatternUtils mLockPatternUtils;
@@ -92,7 +95,6 @@
             mLockPatternView.clearPattern();
         }
     };
-    private Rect mTempRect = new Rect();
     @VisibleForTesting
     KeyguardMessageArea mSecurityMessageDisplay;
     private View mEcaView;
@@ -199,6 +201,15 @@
     }
 
     @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        mLockPatternView.getLocationOnScreen(mTmpPosition);
+        mLockPatternScreenBounds.set(mTmpPosition[0], mTmpPosition[1],
+                mTmpPosition[0] + mLockPatternView.getWidth(),
+                mTmpPosition[1] + mLockPatternView.getHeight());
+    }
+
+    @Override
     public void reset() {
         // reset lock pattern
         mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
@@ -233,9 +244,7 @@
 
     @Override
     public boolean disallowInterceptTouch(MotionEvent event) {
-        mTempRect.set(mLockPatternView.getLeft(), mLockPatternView.getTop(),
-                mLockPatternView.getRight(), mLockPatternView.getBottom());
-        return mTempRect.contains((int) event.getX(), (int) event.getY());
+        return mLockPatternScreenBounds.contains((int) event.getRawX(), (int) event.getRawY());
     }
 
     /** TODO: hook this up */
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 45c19ad..e66a8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -31,7 +31,9 @@
 import android.view.WindowManager;
 
 import com.android.internal.os.SomeArgs;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUI;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.statusbar.CommandQueue;
 
 /**
@@ -58,6 +60,7 @@
     private IBiometricServiceReceiverInternal mReceiver;
     private boolean mDialogShowing;
     private Callback mCallback = new Callback();
+    private WakefulnessLifecycle mWakefulnessLifecycle;
 
     private Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
@@ -133,6 +136,16 @@
         }
     }
 
+    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
+        @Override
+        public void onStartedGoingToSleep() {
+            if (mDialogShowing) {
+                if (DEBUG) Log.d(TAG, "User canceled due to screen off");
+                mHandler.obtainMessage(MSG_USER_CANCELED).sendToTarget();
+            }
+        }
+    };
+
     @Override
     public void start() {
         final PackageManager pm = mContext.getPackageManager();
@@ -141,6 +154,8 @@
                 || pm.hasSystemFeature(PackageManager.FEATURE_IRIS)) {
             getComponent(CommandQueue.class).addCallback(this);
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+            mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
+            mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 8aad0f8..f60e95e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -18,6 +18,9 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
 
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.view.LayoutInflater;
 
@@ -37,6 +40,7 @@
 
     private final String mKey;
     private final String mGroupId;
+    private String mAppName;
     private final BubbleExpandedView.OnBubbleBlockedListener mListener;
 
     private boolean mInflated;
@@ -45,6 +49,7 @@
     BubbleExpandedView expandedView;
     private long mLastUpdated;
     private long mLastAccessed;
+    private PackageManager mPm;
 
     public static String groupId(NotificationEntry entry) {
         UserHandle user = entry.notification.getUser();
@@ -53,16 +58,33 @@
 
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
-    Bubble(NotificationEntry e) {
-        this (e, null);
+    Bubble(Context context, NotificationEntry e) {
+        this (context, e, null);
     }
 
-    Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) {
+    Bubble(Context context, NotificationEntry e,
+            BubbleExpandedView.OnBubbleBlockedListener listener) {
         entry = e;
         mKey = e.key;
         mLastUpdated = e.notification.getPostTime();
         mGroupId = groupId(e);
         mListener = listener;
+
+        mPm = context.getPackageManager();
+        ApplicationInfo info;
+        try {
+            info = mPm.getApplicationInfo(
+                entry.notification.getPackageName(),
+                PackageManager.MATCH_UNINSTALLED_PACKAGES
+                    | PackageManager.MATCH_DISABLED_COMPONENTS
+                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+            if (info != null) {
+                mAppName = String.valueOf(mPm.getApplicationLabel(info));
+            }
+        } catch (PackageManager.NameNotFoundException unused) {
+            mAppName = entry.notification.getPackageName();
+        }
     }
 
     public String getKey() {
@@ -77,6 +99,10 @@
         return entry.notification.getPackageName();
     }
 
+    public String getAppName() {
+        return mAppName;
+    }
+
     boolean isInflated() {
         return mInflated;
     }
@@ -97,9 +123,9 @@
 
         expandedView = (BubbleExpandedView) inflater.inflate(
                 R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
-        expandedView.setEntry(entry, stackView);
-
+        expandedView.setEntry(entry, stackView, mAppName);
         expandedView.setOnBlockedListener(mListener);
+
         mInflated = true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 48edf67..dcc0419 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -40,6 +40,7 @@
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
@@ -193,7 +194,7 @@
             if (shouldCollapse) {
                 collapseStack();
             }
-            updateVisibility();
+            updateStack();
         }
     }
 
@@ -381,6 +382,10 @@
      * @param notif the notification associated with this bubble.
      */
     void updateBubble(NotificationEntry notif) {
+        // If this is an interruptive notif, mark that it's interrupted
+        if (notif.importance >= NotificationManager.IMPORTANCE_HIGH) {
+            notif.setInterruption();
+        }
         mBubbleData.notificationEntryUpdated(notif);
     }
 
@@ -534,10 +539,11 @@
             }
         }
 
+        // Runs on state change.
         @Override
         public void apply() {
             mNotificationEntryManager.updateNotifications();
-            updateVisibility();
+            updateStack();
 
             if (DEBUG) {
                 Log.d(TAG, "[BubbleData]");
@@ -554,34 +560,31 @@
     };
 
     /**
-     * Lets any listeners know if bubble state has changed.
+     * Updates the visibility of the bubbles based on current state.
+     * Does not un-bubble, just hides or un-hides. Notifies any
+     * {@link BubbleStateChangeListener}s of visibility changes.
+     * Updates stack description for TalkBack focus.
      */
-    private void updateBubblesShowing() {
+    public void updateStack() {
         if (mStackView == null) {
             return;
         }
-
-        boolean hadBubbles = mStatusBarWindowController.getBubblesShowing();
-        boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE;
-        mStatusBarWindowController.setBubblesShowing(hasBubblesShowing);
-        if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) {
-            mStateChangeListener.onHasBubblesChanged(hasBubblesShowing);
-        }
-    }
-
-    /**
-     * Updates the visibility of the bubbles based on current state.
-     * Does not un-bubble, just hides or un-hides. Will notify any
-     * {@link BubbleStateChangeListener}s if visibility changes.
-     */
-    public void updateVisibility() {
         if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) {
             // Bubbles only appear in unlocked shade
             mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
         } else if (mStackView != null) {
             mStackView.setVisibility(INVISIBLE);
         }
-        updateBubblesShowing();
+
+        // Let listeners know if bubble state changed.
+        boolean hadBubbles = mStatusBarWindowController.getBubblesShowing();
+        boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE;
+        mStatusBarWindowController.setBubblesShowing(hasBubblesShowing);
+        if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) {
+            mStateChangeListener.onHasBubblesChanged(hasBubblesShowing);
+        }
+
+        mStackView.updateContentDescription();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 9156e06..1858244 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -178,7 +178,7 @@
         Bubble bubble = getBubbleWithKey(entry.key);
         if (bubble == null) {
             // Create a new bubble
-            bubble = new Bubble(entry, this::onBubbleBlocked);
+            bubble = new Bubble(mContext, entry, this::onBubbleBlocked);
             doAdd(bubble);
             trim();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 39867c3..fa137a1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -244,9 +244,10 @@
     /**
      * Sets the notification entry used to populate this view.
      */
-    public void setEntry(NotificationEntry entry, BubbleStackView stackView) {
+    public void setEntry(NotificationEntry entry, BubbleStackView stackView, String appName) {
         mStackView = stackView;
         mEntry = entry;
+        mAppName = appName;
 
         ApplicationInfo info;
         try {
@@ -257,12 +258,10 @@
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE);
             if (info != null) {
-                mAppName = String.valueOf(mPm.getApplicationLabel(info));
                 mAppIcon = mPm.getApplicationIcon(info);
             }
         } catch (PackageManager.NameNotFoundException e) {
-            // Ahh... just use package name
-            mAppName = entry.notification.getPackageName();
+            // Do nothing.
         }
         if (mAppIcon == null) {
             mAppIcon = mPm.getDefaultActivityIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 4fef157..4ad3a33 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -23,6 +23,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
+import android.app.Notification;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.ColorMatrix;
@@ -553,6 +554,43 @@
         return false;
     }
 
+    /**
+     * Update content description for a11y TalkBack.
+     */
+    public void updateContentDescription() {
+        if (mBubbleData.getBubbles().isEmpty()) {
+            return;
+        }
+        Bubble topBubble = mBubbleData.getBubbles().get(0);
+        String appName = topBubble.getAppName();
+        Notification notification = topBubble.entry.notification.getNotification();
+        CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
+        String titleStr = getResources().getString(R.string.stream_notification);
+        if (titleCharSeq != null) {
+            titleStr = titleCharSeq.toString();
+        }
+        int moreCount = mBubbleContainer.getChildCount() - 1;
+
+        // Example: Title from app name.
+        String singleDescription = getResources().getString(
+                R.string.bubble_content_description_single, titleStr, appName);
+
+        // Example: Title from app name and 4 more.
+        String stackDescription = getResources().getString(
+                R.string.bubble_content_description_stack, titleStr, appName, moreCount);
+
+        if (mIsExpanded) {
+            // TODO(b/129522932) - update content description for each bubble in expanded view.
+        } else {
+            // Collapsed stack.
+            if (moreCount > 0) {
+                mBubbleContainer.setContentDescription(stackDescription);
+            } else {
+                mBubbleContainer.setContentDescription(singleDescription);
+            }
+        }
+    }
+
     private void updateSystemGestureExcludeRects() {
         // Exclude the region occupied by the first BubbleView in the stack
         Rect excludeZone = mSystemGestureExclusionRects.get(0);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index e1462d1..03165f4 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -42,6 +42,8 @@
         listView.setReverseSublists(shouldReverseSublists());
         listView.setReverseItems(shouldReverseListItems());
         listView.setSwapRowsAndColumns(shouldSwapRowsAndColumns());
+
+        fixNavBarClipping();
     }
 
     @Override
@@ -73,6 +75,19 @@
         }
     }
 
+    /**
+     * Allows the dialog to clip over the navbar, which prevents shadows and animations from being
+     * cut off.
+     */
+    private void fixNavBarClipping() {
+        ViewGroup parent = (ViewGroup) this.getParent();
+        ViewGroup parentParent = (ViewGroup) parent.getParent();
+        parent.setClipChildren(false);
+        parent.setClipToPadding(false);
+        parentParent.setClipChildren(false);
+        parentParent.setClipToPadding(false);
+    }
+
     @Override
     protected ListGridLayout getListView() {
         return (ListGridLayout) super.getListView();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 4590470..35b8d203 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -30,6 +30,7 @@
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
 import android.media.MediaMetadata;
+import android.media.session.PlaybackState;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Trace;
@@ -57,6 +58,7 @@
 import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -98,6 +100,7 @@
     private final Date mCurrentTime = new Date();
     private final Handler mHandler;
     private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
+    private final HashSet<Integer> mMediaInvisibleStates;
     private ZenModeController mZenModeController;
     private String mDatePattern;
     private DateFormat mDateFormat;
@@ -113,6 +116,7 @@
     private StatusBarStateController mStatusBarStateController;
     protected MediaMetadata mMediaMetaData;
     protected boolean mDozing;
+    private boolean mMediaIsVisible;
 
     /**
      * Receiver responsible for time ticking and updating the date format.
@@ -169,6 +173,11 @@
         mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
         mDndUri = Uri.parse(KEYGUARD_DND_URI);
         mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
+
+        mMediaInvisibleStates = new HashSet<>();
+        mMediaInvisibleStates.add(PlaybackState.STATE_NONE);
+        mMediaInvisibleStates.add(PlaybackState.STATE_STOPPED);
+        mMediaInvisibleStates.add(PlaybackState.STATE_PAUSED);
     }
 
     /**
@@ -209,31 +218,33 @@
     }
 
     protected boolean needsMediaLocked() {
-        return mMediaMetaData != null && mDozing;
+        return mMediaMetaData != null && mMediaIsVisible && mDozing;
     }
 
     protected void addMediaLocked(ListBuilder listBuilder) {
-        if (mMediaMetaData != null) {
-            CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE);
-            if (TextUtils.isEmpty(title)) {
-                title = getContext().getResources().getString(R.string.music_controls_no_title);
+        if (mMediaMetaData == null) {
+            return;
+        }
+
+        CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE);
+        if (TextUtils.isEmpty(title)) {
+            title = getContext().getResources().getString(R.string.music_controls_no_title);
+        }
+        listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title));
+
+        CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST);
+        if (!TextUtils.isEmpty(album)) {
+            RowBuilder albumBuilder = new RowBuilder(mMediaUri);
+            albumBuilder.setTitle(album);
+
+            Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
+            IconCompat mediaIconCompat = mediaIcon == null ? null
+                    : IconCompat.createFromIcon(getContext(), mediaIcon);
+            if (mediaIconCompat != null) {
+                albumBuilder.addEndItem(mediaIconCompat, ListBuilder.ICON_IMAGE);
             }
-            listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title));
 
-            CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST);
-            if (!TextUtils.isEmpty(album)) {
-                RowBuilder albumBuilder = new RowBuilder(mMediaUri);
-                albumBuilder.setTitle(album);
-
-                Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
-                IconCompat mediaIconCompat = mediaIcon == null ? null
-                        : IconCompat.createFromIcon(getContext(), mediaIcon);
-                if (mediaIconCompat != null) {
-                    albumBuilder.addEndItem(mediaIconCompat, ListBuilder.ICON_IMAGE);
-                }
-
-                listBuilder.addRow(albumBuilder);
-            }
+            listBuilder.addRow(albumBuilder);
         }
     }
 
@@ -411,9 +422,14 @@
      * @param metadata New metadata.
      */
     @Override
-    public void onMetadataChanged(MediaMetadata metadata) {
+    public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
         synchronized (this) {
+            boolean nextVisible = !mMediaInvisibleStates.contains(state);
+            if (nextVisible == mMediaIsVisible && metadata == mMediaMetaData) {
+                return;
+            }
             mMediaMetaData = metadata;
+            mMediaIsVisible = nextVisible;
         }
         notifyChange();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index af2b767..a9fe54b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -21,7 +21,6 @@
 import android.annotation.ColorInt;
 import android.annotation.UserIdInt;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
@@ -32,9 +31,7 @@
 import android.content.IntentFilter;
 import android.graphics.Color;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
-import android.util.Log;
 import android.view.View;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -56,7 +53,9 @@
      */
     static final String EXTRA_TASK_DESCRIPTION =
             "com.android.systemui.keyguard.extra.TASK_DESCRIPTION";
-  
+
+    private static final int REQUEST_CODE_CONFIRM_CREDENTIALS = 1;
+
     /**
      * Cached keyguard manager instance populated by {@link #getKeyguardManager}.
      * @see KeyguardManager
@@ -111,7 +110,6 @@
     @Override
     public void onBackPressed() {
         // Ignore back presses.
-        return;
     }
 
     @Override
@@ -151,26 +149,26 @@
                 PendingIntent.FLAG_ONE_SHOT |
                 PendingIntent.FLAG_IMMUTABLE, options.toBundle());
 
-        credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
-        try {
-            ActivityManager.getService().startConfirmDeviceCredentialIntent(credential,
-                    getChallengeOptions().toBundle());
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to start confirm credential intent", e);
+        if (target != null) {
+            credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
+        }
+
+        startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CODE_CONFIRM_CREDENTIALS &&  resultCode != RESULT_OK) {
+            // The user dismissed the challenge, don't show it again.
+            goToHomeScreen();
         }
     }
 
-    private ActivityOptions getChallengeOptions() {
-        // If we are taking up the whole screen, just use the default animation of clipping the
-        // credentials activity into the entire foreground.
-        if (!isInMultiWindowMode()) {
-            return ActivityOptions.makeBasic();
-        }
-
-        // Otherwise, animate the transition from this part of the screen to fullscreen
-        // using our own decor as the starting position.
-        final View view = getWindow().getDecorView();
-        return ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight());
+    private void goToHomeScreen() {
+        final Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        startActivity(homeIntent);
     }
 
     private KeyguardManager getKeyguardManager() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index b9e0c60..75ef185 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -150,8 +150,8 @@
             if (state != null) {
                 if (!isPlaybackActive(state.getState())) {
                     clearCurrentMediaNotification();
-                    dispatchUpdateMediaMetaData(true /* changed */, true /* allowAnimation */);
                 }
+                dispatchUpdateMediaMetaData(true /* changed */, true /* allowAnimation */);
             }
         }
 
@@ -242,7 +242,8 @@
 
     public void addCallback(MediaListener callback) {
         mMediaListeners.add(callback);
-        callback.onMetadataChanged(mMediaMetadata);
+        callback.onMetadataOrStateChanged(mMediaMetadata,
+                getMediaControllerPlaybackState(mMediaController));
     }
 
     public void removeCallback(MediaListener callback) {
@@ -357,9 +358,10 @@
         if (mPresenter != null) {
             mPresenter.updateMediaMetaData(changed, allowEnterAnimation);
         }
+        @PlaybackState.State int state = getMediaControllerPlaybackState(mMediaController);
         ArrayList<MediaListener> callbacks = new ArrayList<>(mMediaListeners);
         for (int i = 0; i < callbacks.size(); i++) {
-            callbacks.get(i).onMetadataChanged(mMediaMetadata);
+            callbacks.get(i).onMetadataOrStateChanged(mMediaMetadata, state);
         }
     }
 
@@ -698,6 +700,12 @@
     }
 
     public interface MediaListener {
-        void onMetadataChanged(MediaMetadata metadata);
+        /**
+         * Called whenever there's new metadata or playback state.
+         * @param metadata Current metadata.
+         * @param state Current playback state
+         * @see PlaybackState.State
+         */
+        void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 033c4fb..6552fe6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -40,7 +40,6 @@
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
 import android.util.FloatProperty;
 import android.util.Log;
 import android.util.Property;
@@ -72,12 +71,12 @@
     /**
      * Status icons are currently drawn with the intention of being 17dp tall, but we
      * want to scale them (in a way that doesn't require an asset dump) down 2dp. So
-     * 17dp * (15 / 17) = 15dp, the new height.
+     * 17dp * (15 / 17) = 15dp, the new height. After the first call to {@link #reloadDimens} all
+     * values will be in px.
      */
-    private static final float SYSTEM_ICON_DESIRED_HEIGHT = 15f;
-    private static final float SYSTEM_ICON_INTRINSIC_HEIGHT = 17f;
-    private static final float SYSTEM_ICON_SCALE =
-            SYSTEM_ICON_DESIRED_HEIGHT / SYSTEM_ICON_INTRINSIC_HEIGHT;
+    private float mSystemIconDesiredHeight = 15f;
+    private float mSystemIconIntrinsicHeight = 17f;
+    private float mSystemIconDefaultScale = mSystemIconDesiredHeight / mSystemIconIntrinsicHeight;
     private final int ANIMATION_DURATION_FAST = 100;
 
     public static final int STATE_ICON = 0;
@@ -209,21 +208,20 @@
     // Makes sure that all icons are scaled to the same height (15dp). If we cannot get a height
     // for the icon, it uses the default SCALE (15f / 17f) which is the old behavior
     private void updateIconScaleForSystemIcons() {
-        float iconHeight = getIconHeightInDps();
+        float iconHeight = getIconHeight();
         if (iconHeight != 0) {
-            mIconScale = SYSTEM_ICON_DESIRED_HEIGHT / iconHeight;
+            mIconScale = mSystemIconDesiredHeight / iconHeight;
         } else {
-            mIconScale = SYSTEM_ICON_SCALE;
+            mIconScale = mSystemIconDefaultScale;
         }
     }
 
-    private float getIconHeightInDps() {
+    private float getIconHeight() {
         Drawable d = getDrawable();
         if (d != null) {
-            return ((float) getDrawable().getIntrinsicHeight() * DisplayMetrics.DENSITY_DEFAULT)
-                    / mDensity;
+            return (float) getDrawable().getIntrinsicHeight();
         } else {
-            return SYSTEM_ICON_INTRINSIC_HEIGHT;
+            return mSystemIconIntrinsicHeight;
         }
     }
 
@@ -265,6 +263,11 @@
         if (applyRadius) {
             mDotRadius = mStaticDotRadius;
         }
+        mSystemIconDesiredHeight = res.getDimension(
+                com.android.internal.R.dimen.status_bar_system_icon_size);
+        mSystemIconIntrinsicHeight = res.getDimension(
+                com.android.internal.R.dimen.status_bar_system_icon_intrinsic_size);
+        mSystemIconDefaultScale = mSystemIconDesiredHeight / mSystemIconIntrinsicHeight;
     }
 
     public void setNotification(StatusBarNotification notification) {
@@ -272,6 +275,7 @@
         if (notification != null) {
             setContentDescription(notification.getNotification());
         }
+        maybeUpdateIconScaleDimens();
     }
 
     public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -280,7 +284,7 @@
         mBlocked = false;
         mAlwaysScaleIcon = true;
         reloadDimens();
-        updateIconScaleForNotifications();
+        maybeUpdateIconScaleDimens();
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
     }
 
@@ -854,7 +858,7 @@
     public void setDark(boolean dark, boolean fade, long delay) {
         mDozer.setIntensityDark(f -> {
             mDarkAmount = f;
-            updateIconScaleForNotifications();
+            maybeUpdateIconScaleDimens();
             updateDecorColor();
             updateIconColor();
             updateAllowAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index f93c5f0..a3e3426 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -46,6 +46,7 @@
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
 import javax.inject.Inject;
@@ -71,6 +72,7 @@
     private final AccessibilityController mAccessibilityController;
     private final DockManager mDockManager;
     private final Handler mMainHandler;
+    private final KeyguardMonitor mKeyguardMonitor;
 
     private int mLastState = 0;
     private boolean mTransientBiometricsError;
@@ -91,7 +93,16 @@
     private int mIconRes;
     private boolean mWasPulsingOnThisFrame;
     private boolean mWakeAndUnlockRunning;
+    private boolean mKeyguardShowing;
 
+    private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
+            new KeyguardMonitor.Callback() {
+                @Override
+                public void onKeyguardShowingChanged() {
+                    mKeyguardShowing = mKeyguardMonitor.isShowing();
+                    update(false /* force */);
+                }
+            };
     private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
     private final DockManager.DockEventListener mDockEventListener =
             new DockManager.DockEventListener() {
@@ -150,6 +161,7 @@
             StatusBarStateController statusBarStateController,
             ConfigurationController configurationController,
             AccessibilityController accessibilityController,
+            KeyguardMonitor keyguardMonitor,
             @Nullable DockManager dockManager,
             @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
         super(context, attrs);
@@ -159,6 +171,7 @@
         mAccessibilityController = accessibilityController;
         mConfigurationController = configurationController;
         mStatusBarStateController = statusBarStateController;
+        mKeyguardMonitor = keyguardMonitor;
         mDockManager = dockManager;
         mMainHandler = mainHandler;
     }
@@ -168,6 +181,7 @@
         super.onAttachedToWindow();
         mStatusBarStateController.addCallback(this);
         mConfigurationController.addCallback(this);
+        mKeyguardMonitor.addCallback(mKeyguardMonitorCallback);
         mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
         mUnlockMethodCache.addListener(this);
         mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
@@ -183,6 +197,7 @@
         mStatusBarStateController.removeCallback(this);
         mConfigurationController.removeCallback(this);
         mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
+        mKeyguardMonitor.removeCallback(mKeyguardMonitorCallback);
         mUnlockMethodCache.removeListener(this);
         if (mDockManager != null) {
             mDockManager.removeListener(mDockEventListener);
@@ -379,7 +394,7 @@
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
         if (mTransientBiometricsError) {
             return STATE_BIOMETRICS_ERROR;
-        } else if (mUnlockMethodCache.canSkipBouncer() && !mSimLocked) {
+        } else if ((mUnlockMethodCache.canSkipBouncer() || !mKeyguardShowing) && !mSimLocked) {
             return STATE_LOCK_OPEN;
         } else if (updateMonitor.isFaceDetectionRunning()) {
             return STATE_SCANNING_FACE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
index 4603ba6..4f223c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.os.VibrationEffect;
+import android.util.DisplayMetrics;
 import android.util.MathUtils;
 import android.view.ContextThemeWrapper;
 import android.view.MotionEvent;
@@ -47,14 +48,14 @@
 
 public class NavigationBarEdgePanel extends View {
 
-    private static final long COLOR_ANIMATION_DURATION_MS = 100;
-    private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 140;
+    private static final long COLOR_ANIMATION_DURATION_MS = 120;
+    private static final long DISAPPEAR_FADE_ANIMATION_DURATION_MS = 80;
     private static final long DISAPPEAR_ARROW_ANIMATION_DURATION_MS = 100;
 
     /**
-     * The minimum time required since the first vibration effect to receive a second one
+     * The time required since the first vibration effect to automatically trigger a click
      */
-    private static final int MIN_TIME_BETWEEN_EFFECTS_MS = 120;
+    private static final int GESTURE_DURATION_FOR_CLICK_MS = 400;
 
     /**
      * The size of the protection of the arrow in px. Only used if this is not background protected
@@ -79,7 +80,7 @@
     /**
      * The angle that is added per 1000 px speed to the angle of the leg
      */
-    private static final int ARROW_ANGLE_ADDED_PER_1000_SPEED = 8;
+    private static final int ARROW_ANGLE_ADDED_PER_1000_SPEED = 4;
 
     /**
      * The maximum angle offset allowed due to speed
@@ -92,15 +93,15 @@
     private static final float ARROW_THICKNESS_DP = 2.5f;
 
     /**
-     * The amount of rubber banding we do for the horizontal translation beyond the base translation
+     * The amount of rubber banding we do for the vertical translation
      */
-    private static final int RUBBER_BAND_AMOUNT = 10;
+    private static final int RUBBER_BAND_AMOUNT = 15;
 
     /**
      * The interpolator used to rubberband
      */
     private static final Interpolator RUBBER_BAND_INTERPOLATOR
-            = new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT, 1.0f, 1.0f, 1.0f);
+            = new PathInterpolator(1.0f / 5.0f, 1.0f, 1.0f, 1.0f);
 
     /**
      * The amount of rubber banding we do for the translation before base translation
@@ -189,6 +190,7 @@
     private int mCurrentArrowColor;
     private float mDisappearAmount;
     private long mVibrationTime;
+    private int mScreenSize;
 
     private DynamicAnimation.OnAnimationEndListener mSetGoneEndListener
             = new DynamicAnimation.OnAnimationEndListener() {
@@ -281,9 +283,8 @@
         mAngleAnimation =
                 new SpringAnimation(this, CURRENT_ANGLE);
         mAngleAppearForce = new SpringForce()
-                .setStiffness(SpringForce.STIFFNESS_LOW)
-                .setDampingRatio(0.4f)
-                .setFinalPosition(ARROW_ANGLE_WHEN_EXTENDED_DEGREES);
+                .setStiffness(500)
+                .setDampingRatio(0.5f);
         mAngleDisappearForce = new SpringForce()
                 .setStiffness(SpringForce.STIFFNESS_MEDIUM)
                 .setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY)
@@ -447,13 +448,14 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
 
-        // TODO: read the gesture length from the nav controller.
         mMaxTranslation = getWidth() - mArrowPaddingEnd;
     }
 
     private void loadDimens() {
         mArrowPaddingEnd = getContext().getResources().getDimensionPixelSize(
                 R.dimen.navigation_edge_panel_padding);
+        DisplayMetrics metrics = getResources().getDisplayMetrics();
+        mScreenSize = Math.min(metrics.widthPixels, metrics.heightPixels);
     }
 
     private void updateArrowDirection() {
@@ -510,7 +512,7 @@
         if (!mArrowsPointLeft) {
             x = -x;
         }
-        float extent = 1.0f - mDisappearAmount;
+        float extent = MathUtils.lerp(1.0f, 0.75f, mDisappearAmount);
         x = x * extent;
         y = y * extent;
         mArrowPath.reset();
@@ -529,27 +531,29 @@
     }
 
     private void triggerBack() {
-        if (SystemClock.uptimeMillis() - mVibrationTime >= MIN_TIME_BETWEEN_EFFECTS_MS) {
-            mVibratorHelper.vibrate(VibrationEffect.EFFECT_CLICK);
-        }
         mVelocityTracker.computeCurrentVelocity(1000);
         // Only do the extra translation if we're not already flinging
-        boolean doExtraTranslation = Math.abs(mVelocityTracker.getXVelocity()) < 1000;
-        if (doExtraTranslation) {
-            setDesiredTranslation(mDesiredTranslation + dp(16), true /* animate */);
+        boolean isSlow = Math.abs(mVelocityTracker.getXVelocity()) < 500;
+        if (isSlow
+                || SystemClock.uptimeMillis() - mVibrationTime >= GESTURE_DURATION_FOR_CLICK_MS) {
+            mVibratorHelper.vibrate(VibrationEffect.EFFECT_CLICK);
         }
 
         // Let's also snap the angle a bit
-        if (mAngleOffset < -4) {
-            mAngleOffset = Math.max(-16, mAngleOffset - 16);
+        if (mAngleOffset > -4) {
+            mAngleOffset = Math.max(-8, mAngleOffset - 8);
             updateAngle(true /* animated */);
         }
 
         // Finally, after the translation, animate back and disappear the arrow
         Runnable translationEnd = () -> {
-            setTriggerBack(false /* false */, true /* animate */);
+            // let's snap it back
+            mAngleOffset = Math.max(0, mAngleOffset + 8);
+            updateAngle(true /* animated */);
+
             mTranslationAnimation.setSpring(mTriggerBackSpring);
-            setDesiredTranslation(0, true /* animated */);
+            // Translate the arrow back a bit to make for a nice transition
+            setDesiredTranslation(mDesiredTranslation - dp(32), true /* animated */);
             animate().alpha(0f).setDuration(DISAPPEAR_FADE_ANIMATION_DURATION_MS)
                     .withEndAction(() -> setVisibility(GONE));
             mArrowDisappearAnimation.start();
@@ -584,6 +588,7 @@
         setTriggerBack(false /* triggerBack */, false /* animated */);
         setDesiredTranslation(0, false /* animated */);
         setCurrentTranslation(0);
+        updateAngle(false /* animate */);
         mPreviousTouchTranslation = 0;
         mTotalTouchDelta = 0;
         mVibrationTime = 0;
@@ -621,7 +626,7 @@
         // Let's make sure we only go to the baseextend and apply rubberbanding afterwards
         if (touchTranslation > mBaseTranslation) {
             float diff = touchTranslation - mBaseTranslation;
-            float progress = MathUtils.saturate(diff / (mBaseTranslation * RUBBER_BAND_AMOUNT));
+            float progress = MathUtils.saturate(diff / (mScreenSize - mBaseTranslation));
             progress = RUBBER_BAND_INTERPOLATOR.getInterpolation(progress)
                     * (mMaxTranslation - mBaseTranslation);
             touchTranslation = mBaseTranslation + progress;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 9e0aff0..3b3336b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -107,6 +107,8 @@
 
     @Override
     public void setAutoDim(boolean autoDim) {
+        // Ensure we aren't in gestural nav if we are triggering auto dim
+        if (autoDim && NavBarTintController.isEnabled(mView.getContext(), mNavBarMode)) return;
         if (mAutoDim == autoDim) return;
         mAutoDim = autoDim;
         applyLightsOut(true, false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
index d59319e..2b0bb21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RegionSamplingHelper.java
@@ -27,6 +27,7 @@
 import android.view.CompositionSamplingListener;
 import android.view.SurfaceControl;
 import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver;
 
 import com.android.systemui.R;
@@ -153,8 +154,12 @@
         boolean isSamplingEnabled = mSamplingEnabled && !mSamplingRequestBounds.isEmpty()
                 && (mSampledView.isAttachedToWindow() || mFirstSamplingAfterStart);
         if (isSamplingEnabled) {
-            SurfaceControl stopLayerControl = mSampledView.getViewRootImpl().getSurfaceControl();
-            if (!stopLayerControl.isValid()) {
+            ViewRootImpl viewRootImpl = mSampledView.getViewRootImpl();
+            SurfaceControl stopLayerControl = null;
+            if (viewRootImpl != null) {
+                 stopLayerControl = viewRootImpl.getSurfaceControl();
+            }
+            if (stopLayerControl == null || !stopLayerControl.isValid()) {
                 if (!mWaitingOnDraw) {
                     mWaitingOnDraw = true;
                     // The view might be attached but we haven't drawn yet, so wait until the
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 33b2e6e..364a0f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -103,13 +103,13 @@
         mEntryB3 = createBubbleEntry(1, "b3", "package.b");
         mEntryC1 = createBubbleEntry(1, "c1", "package.c");
 
-        mBubbleA1 = new Bubble(mEntryA1);
-        mBubbleA2 = new Bubble(mEntryA2);
-        mBubbleA3 = new Bubble(mEntryA3);
-        mBubbleB1 = new Bubble(mEntryB1);
-        mBubbleB2 = new Bubble(mEntryB2);
-        mBubbleB3 = new Bubble(mEntryB3);
-        mBubbleC1 = new Bubble(mEntryC1);
+        mBubbleA1 = new Bubble(mContext, mEntryA1);
+        mBubbleA2 = new Bubble(mContext, mEntryA2);
+        mBubbleA3 = new Bubble(mContext, mEntryA3);
+        mBubbleB1 = new Bubble(mContext, mEntryB1);
+        mBubbleB2 = new Bubble(mContext, mEntryB2);
+        mBubbleB3 = new Bubble(mContext, mEntryB3);
+        mBubbleC1 = new Bubble(mContext, mEntryC1);
 
         mBubbleData = new BubbleData(getContext());
 
@@ -803,4 +803,4 @@
     private static <T> List<T> listOf(T... a) {
         return ImmutableList.copyOf(a);
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index c534de7..355e260 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -29,6 +29,7 @@
 import android.app.AlarmManager;
 import android.content.ContentResolver;
 import android.media.MediaMetadata;
+import android.media.session.PlaybackState;
 import android.net.Uri;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
@@ -105,7 +106,7 @@
         MediaMetadata metadata = mock(MediaMetadata.class);
         when(metadata.getText(any())).thenReturn("metadata");
         mProvider.onDozingChanged(true);
-        mProvider.onMetadataChanged(metadata);
+        mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
         mProvider.onBindSlice(mProvider.getUri());
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_ARTIST));
@@ -170,7 +171,7 @@
     public void onMetadataChanged_updatesSlice() {
         mProvider.onDozingChanged(true);
         reset(mContentResolver);
-        mProvider.onMetadataChanged(mock(MediaMetadata.class));
+        mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
 
         // Hides after waking up
@@ -181,7 +182,7 @@
 
     @Test
     public void onDozingChanged_updatesSliceIfMedia() {
-        mProvider.onMetadataChanged(mock(MediaMetadata.class));
+        mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
         reset(mContentResolver);
         // Show media when dozing
         mProvider.onDozingChanged(true);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 5fd14a3..a5a4fec 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7294,6 +7294,7 @@
     ACTION_VERIFY_SLICE_OTHER_EXCEPTION = 1727;
 
     // ---- Skipping ahead to avoid conflicts between master and release branches.
+
     // OPEN: Settings > System > Gestures > Global Actions Panel
     // CATEGORY: SETTINGS
     // OS: Q
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java
new file mode 100644
index 0000000..dd1b84b
--- /dev/null
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureMetricsLogger.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
+import android.service.contentcapture.FlushMetrics;
+import android.util.StatsLog;
+
+import java.util.List;
+
+/** @hide */
+public final class ContentCaptureMetricsLogger {
+    /**
+     * Class only contains static utility functions, and should not be instantiated
+     */
+    private ContentCaptureMetricsLogger() {
+    }
+
+    /** @hide */
+    public static void writeServiceEvent(int eventType, @NonNull String serviceName,
+            @Nullable String targetPackage) {
+        StatsLog.write(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS, eventType, serviceName,
+                targetPackage);
+    }
+
+    /** @hide */
+    public static void writeServiceEvent(int eventType, @NonNull ComponentName service,
+            @Nullable ComponentName target) {
+        writeServiceEvent(eventType, ComponentName.flattenToShortString(service),
+                ComponentName.flattenToShortString(target));
+    }
+
+    /** @hide */
+    public static void writeServiceEvent(int eventType, @NonNull ComponentName service,
+            @Nullable String targetPackage) {
+        writeServiceEvent(eventType, ComponentName.flattenToShortString(service), targetPackage);
+    }
+
+    /** @hide */
+    public static void writeServiceEvent(int eventType, @NonNull ComponentName service) {
+        writeServiceEvent(eventType, ComponentName.flattenToShortString(service), null);
+    }
+
+    /** @hide */
+    public static void writeSetWhitelistEvent(@Nullable ComponentName service,
+            @Nullable List<String> packages, @Nullable List<ComponentName> activities) {
+        final String serviceName = ComponentName.flattenToShortString(service);
+        StringBuilder stringBuilder = new StringBuilder();
+        if (packages != null && packages.size() > 0) {
+            final int size = packages.size();
+            stringBuilder.append(packages.get(0));
+            for (int i = 1; i < size; i++) {
+                stringBuilder.append(" ");
+                stringBuilder.append(packages.get(i));
+            }
+        }
+        if (activities != null && activities.size() > 0) {
+            stringBuilder.append(" ");
+            stringBuilder.append(activities.get(0).flattenToShortString());
+            final int size = activities.size();
+            for (int i = 1; i < size; i++) {
+                stringBuilder.append(" ");
+                stringBuilder.append(activities.get(i).flattenToShortString());
+            }
+        }
+        StatsLog.write(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS,
+                StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__SET_WHITELIST,
+                serviceName, stringBuilder.toString());
+    }
+
+    /** @hide */
+    public static void writeSessionEvent(int sessionId, int event, int flags,
+            @NonNull ComponentName service, @Nullable ComponentName app, boolean isChildSession) {
+        StatsLog.write(StatsLog.CONTENT_CAPTURE_SESSION_EVENTS, sessionId, event, flags,
+                ComponentName.flattenToShortString(service),
+                ComponentName.flattenToShortString(app), isChildSession);
+    }
+
+    /** @hide */
+    public static void writeSessionFlush(int sessionId, @NonNull ComponentName service,
+            @Nullable ComponentName app, @NonNull FlushMetrics fm,
+            @NonNull ContentCaptureOptions options, int flushReason) {
+        StatsLog.write(StatsLog.CONTENT_CAPTURE_FLUSHED, sessionId,
+                ComponentName.flattenToShortString(service),
+                ComponentName.flattenToShortString(app), fm.sessionStarted, fm.sessionFinished,
+                fm.viewAppearedCount, fm.viewDisappearedCount, fm.viewTextChangedCount,
+                options.maxBufferSize, options.idleFlushingFrequencyMs,
+                options.textChangeFlushingFrequencyMs, flushReason);
+    }
+}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 67c3d01..a186d4e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -24,6 +24,9 @@
 import static android.view.contentcapture.ContentCaptureSession.STATE_NOT_WHITELISTED;
 import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
 
+import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeServiceEvent;
+import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeSessionEvent;
+import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeSetWhitelistEvent;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
@@ -35,6 +38,7 @@
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.content.ComponentName;
+import android.content.ContentCaptureOptions;
 import android.content.pm.ActivityPresentationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -48,6 +52,7 @@
 import android.service.contentcapture.ActivityEvent.ActivityEventType;
 import android.service.contentcapture.ContentCaptureService;
 import android.service.contentcapture.ContentCaptureServiceInfo;
+import android.service.contentcapture.FlushMetrics;
 import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
@@ -55,6 +60,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.StatsLog;
 import android.view.contentcapture.ContentCaptureCondition;
 import android.view.contentcapture.DataRemovalRequest;
 
@@ -231,7 +237,6 @@
         resurrectSessionsLocked();
     }
 
-    // TODO(b/119613670): log metrics
     @GuardedBy("mLock")
     public void startSessionLocked(@NonNull IBinder activityToken,
             @NonNull ActivityPresentationInfo activityPresentationInfo, int sessionId, int uid,
@@ -263,9 +268,14 @@
 
         if (!enabled) {
             // TODO: it would be better to split in differet reasons, like
-            // STATE_DISABLED_NO_SERVICE and STATE_DISABLED_BY_DEVICE_POLICY
+            // STATE_DISABLED_NO and STATE_DISABLED_BY_DEVICE_POLICY
             setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                     /* binder= */ null);
+            // Log metrics.
+            writeSessionEvent(sessionId,
+                    StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__SESSION_NOT_CREATED,
+                    STATE_DISABLED | STATE_NO_SERVICE, serviceComponentName,
+                    componentName, /* isChildSession= */ false);
             return;
         }
         if (serviceComponentName == null) {
@@ -285,6 +295,11 @@
             }
             setClientState(clientReceiver, STATE_DISABLED | STATE_NOT_WHITELISTED,
                     /* binder= */ null);
+            // Log metrics.
+            writeSessionEvent(sessionId,
+                    StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__SESSION_NOT_CREATED,
+                    STATE_DISABLED | STATE_NOT_WHITELISTED, serviceComponentName,
+                    componentName, /* isChildSession= */ false);
             return;
         }
 
@@ -294,6 +309,11 @@
                     + ": ignoring because it already exists for " + existingSession.mActivityToken);
             setClientState(clientReceiver, STATE_DISABLED | STATE_DUPLICATED_ID,
                     /* binder=*/ null);
+            // Log metrics.
+            writeSessionEvent(sessionId,
+                    StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__SESSION_NOT_CREATED,
+                    STATE_DISABLED | STATE_DUPLICATED_ID,
+                    serviceComponentName, componentName, /* isChildSession= */ false);
             return;
         }
 
@@ -302,11 +322,15 @@
         }
 
         if (mRemoteService == null) {
-            // TODO(b/119613670): log metrics
             Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
                     + ": ignoring because service is not set");
             setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                     /* binder= */ null);
+            // Log metrics.
+            writeSessionEvent(sessionId,
+                    StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__SESSION_NOT_CREATED,
+                    STATE_DISABLED | STATE_NO_SERVICE, serviceComponentName,
+                    componentName, /* isChildSession= */ false);
             return;
         }
 
@@ -324,7 +348,6 @@
         newSession.notifySessionStartedLocked(clientReceiver);
     }
 
-    // TODO(b/119613670): log metrics
     @GuardedBy("mLock")
     public void finishSessionLocked(int sessionId) {
         if (!isEnabledLocked()) {
@@ -553,6 +576,7 @@
                         + " for user " + mUserId);
             }
             mMaster.mGlobalContentCaptureOptions.setWhitelist(mUserId, packages, activities);
+            writeSetWhitelistEvent(getServiceComponentName(), packages, activities);
 
             // Must disable session that are not the whitelist anymore...
             final int numSessions = mSessions.size();
@@ -602,7 +626,6 @@
                     mConditionsByPkg.put(packageName, new ArraySet<>(conditions));
                 }
             }
-            // TODO(b/119613670): log metrics
         }
 
         @Override
@@ -616,6 +639,15 @@
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
+            writeServiceEvent(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__SET_DISABLED,
+                    getServiceComponentName());
+        }
+
+        @Override
+        public void writeSessionFlush(int sessionId, ComponentName app, FlushMetrics flushMetrics,
+                ContentCaptureOptions options, int flushReason) {
+            ContentCaptureMetricsLogger.writeSessionFlush(sessionId, getServiceComponentName(), app,
+                    flushMetrics, options, flushReason);
         }
     }
 }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 2171033..18daf32 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -18,6 +18,9 @@
 import static android.view.contentcapture.ContentCaptureHelper.sDebug;
 import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
 
+import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeServiceEvent;
+import static com.android.server.contentcapture.ContentCaptureMetricsLogger.writeSessionEvent;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
@@ -28,6 +31,7 @@
 import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.Slog;
+import android.util.StatsLog;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.DataRemovalRequest;
 
@@ -77,6 +81,8 @@
             if (connected) {
                 try {
                     mService.onConnected(mServerCallback, sVerbose, sDebug);
+                    writeServiceEvent(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_CONNECTED,
+                            mComponentName);
                 } finally {
                     // Update the system-service state, in case the service reconnected after
                     // dying
@@ -84,6 +90,8 @@
                 }
             } else {
                 mService.onDisconnected();
+                writeServiceEvent(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_DISCONNECTED,
+                        mComponentName);
             }
         } catch (Exception e) {
             Slog.w(mTag, "Exception calling onConnectedStateChanged(" + connected + "): " + e);
@@ -102,6 +110,10 @@
             @NonNull IResultReceiver clientReceiver, int initialState) {
         scheduleAsyncRequest(
                 (s) -> s.onSessionStarted(context, sessionId, uid, clientReceiver, initialState));
+        // Metrics logging.
+        writeSessionEvent(sessionId,
+                StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__ON_SESSION_STARTED, initialState,
+                getComponentName(), context.getActivityComponent(), /* is_child_session= */ false);
     }
 
     /**
@@ -110,6 +122,11 @@
      */
     public void onSessionFinished(int sessionId) {
         scheduleAsyncRequest((s) -> s.onSessionFinished(sessionId));
+        // Metrics logging.
+        writeSessionEvent(sessionId,
+                StatsLog.CONTENT_CAPTURE_SESSION_EVENTS__EVENT__ON_SESSION_FINISHED,
+                /* flags= */ 0, getComponentName(), /* app= */ null,
+                /* is_child_session= */ false);
     }
 
     /**
@@ -124,6 +141,8 @@
      */
     public void onDataRemovalRequest(@NonNull DataRemovalRequest request) {
         scheduleAsyncRequest((s) -> s.onDataRemovalRequest(request));
+        writeServiceEvent(StatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_USER_DATA_REMOVED,
+                mComponentName);
     }
 
     /**
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 72899f6..cb61259 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1138,8 +1138,8 @@
                     ? clampPositive(whenElapsed + a.windowLength)
                     : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
         }
-        a.whenElapsed = whenElapsed;
-        a.maxWhenElapsed = maxElapsed;
+        a.expectedWhenElapsed = a.whenElapsed = whenElapsed;
+        a.expectedMaxWhenElapsed = a.maxWhenElapsed = maxElapsed;
         setImplLocked(a, true, doValidate);
     }
 
@@ -1243,7 +1243,7 @@
                 alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
                 // Also schedule its next recurrence
                 final long delta = alarm.count * alarm.repeatInterval;
-                final long nextElapsed = alarm.whenElapsed + delta;
+                final long nextElapsed = alarm.expectedWhenElapsed + delta;
                 setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
                         maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
                         alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
@@ -3596,10 +3596,9 @@
                     // this adjustment will be zero if we're late by
                     // less than one full repeat interval
                     alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
-
                     // Also schedule its next recurrence
                     final long delta = alarm.count * alarm.repeatInterval;
-                    final long nextElapsed = alarm.whenElapsed + delta;
+                    final long nextElapsed = alarm.expectedWhenElapsed + delta;
                     setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
                             maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
                             alarm.repeatInterval, alarm.operation, null, null, alarm.flags, true,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d8f5937..ea71a3b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -735,11 +735,11 @@
          * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
          * method.
          */
-        void put(int key, ProcessRecord value) {
+        void put(ProcessRecord app) {
             synchronized (this) {
-                mPidMap.put(key, value);
+                mPidMap.put(app.pid, app);
             }
-            mAtmInternal.onProcessMapped(key, value.getWindowProcessController());
+            mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController());
         }
 
         /**
@@ -747,11 +747,18 @@
          * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
          * method.
          */
-        void remove(int pid) {
+        void remove(ProcessRecord app) {
+            boolean removed = false;
             synchronized (this) {
-                mPidMap.remove(pid);
+                final ProcessRecord existingApp = mPidMap.get(app.pid);
+                if (existingApp != null && existingApp.startSeq == app.startSeq) {
+                    mPidMap.remove(app.pid);
+                    removed = true;
+                }
             }
-            mAtmInternal.onProcessUnMapped(pid);
+            if (removed) {
+                mAtmInternal.onProcessUnMapped(app.pid);
+            }
         }
 
         /**
@@ -759,17 +766,18 @@
          * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
          * method.
          */
-        boolean removeIfNoThread(int pid) {
+        boolean removeIfNoThread(ProcessRecord app) {
             boolean removed = false;
             synchronized (this) {
-                final ProcessRecord app = get(pid);
-                if (app != null && app.thread == null) {
-                    mPidMap.remove(pid);
+                final ProcessRecord existingApp = get(app.pid);
+                if (existingApp != null && existingApp.startSeq == app.startSeq
+                        && app.thread == null) {
+                    mPidMap.remove(app.pid);
                     removed = true;
                 }
             }
             if (removed) {
-                mAtmInternal.onProcessUnMapped(pid);
+                mAtmInternal.onProcessUnMapped(app.pid);
             }
             return removed;
         }
@@ -1970,7 +1978,7 @@
                 app.getWindowProcessController().setPid(MY_PID);
                 app.maxAdj = ProcessList.SYSTEM_ADJ;
                 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
-                mPidsSelfLocked.put(app.pid, app);
+                mPidsSelfLocked.put(app);
                 mProcessList.updateLruProcessLocked(app, false, null);
                 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
             }
@@ -4601,7 +4609,7 @@
     @GuardedBy("this")
     private final void processStartTimedOutLocked(ProcessRecord app) {
         final int pid = app.pid;
-        boolean gone = mPidsSelfLocked.removeIfNoThread(pid);
+        boolean gone = mPidsSelfLocked.removeIfNoThread(app);
 
         if (gone) {
             Slog.w(TAG, "Process " + app + " failed to attach");
@@ -4658,6 +4666,26 @@
             synchronized (mPidsSelfLocked) {
                 app = mPidsSelfLocked.get(pid);
             }
+            if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) {
+                String processName = null;
+                final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
+                if (pending != null) {
+                    processName = pending.processName;
+                }
+                final String msg = "attachApplicationLocked process:" + processName
+                        + " startSeq:" + startSeq
+                        + " pid:" + pid
+                        + " belongs to another existing app:" + app.processName
+                        + " startSeq:" + app.startSeq;
+                Slog.wtf(TAG, msg);
+                // SafetyNet logging for b/131105245.
+                EventLog.writeEvent(0x534e4554, "131105245", app.startUid, msg);
+                // If there is already an app occupying that pid that hasn't been cleaned up
+                cleanUpApplicationRecordLocked(app, false, false, -1,
+                            true /*replacingPid*/);
+                mPidsSelfLocked.remove(app);
+                app = null;
+            }
         } else {
             app = null;
         }
@@ -4666,7 +4694,7 @@
         // update the internal state.
         if (app == null && startSeq > 0) {
             final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
-            if (pending != null && pending.startUid == callingUid
+            if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq
                     && mProcessList.handleProcessStartedLocked(pending, pid, pending
                             .isUsingWrapper(),
                             startSeq, true)) {
@@ -13642,7 +13670,7 @@
             return true;
         } else if (app.pid > 0 && app.pid != MY_PID) {
             // Goodbye!
-            mPidsSelfLocked.remove(app.pid);
+            mPidsSelfLocked.remove(app);
             mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
             if (app.isolated) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b394eea..dc94c1e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1445,10 +1445,11 @@
         long startTime = SystemClock.elapsedRealtime();
         if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
             checkSlow(startTime, "startProcess: removing from pids map");
-            mService.mPidsSelfLocked.remove(app.pid);
+            mService.mPidsSelfLocked.remove(app);
             mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             checkSlow(startTime, "startProcess: done removing from pids map");
             app.setPid(0);
+            app.startSeq = 0;
         }
 
         if (DEBUG_PROCESSES && mService.mProcessesOnHold.contains(app)) Slog.v(
@@ -1656,6 +1657,14 @@
         app.killedByAm = false;
         app.removed = false;
         app.killed = false;
+        if (app.startSeq != 0) {
+            Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+                    + " with non-zero startSeq:" + app.startSeq);
+        }
+        if (app.pid != 0) {
+            Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
+                    + " with non-zero pid:" + app.pid);
+        }
         final long startSeq = app.startSeq = ++mProcStartSeqCounter;
         app.setStartParams(uid, hostingRecord, seInfo, startTime);
         app.setUsingWrapper(invokeWith != null
@@ -2063,12 +2072,15 @@
         // If there is already an app occupying that pid that hasn't been cleaned up
         if (oldApp != null && !app.isolated) {
             // Clean up anything relating to this pid first
-            Slog.w(TAG, "Reusing pid " + pid
-                    + " while app is still mapped to it");
+            Slog.wtf(TAG, "handleProcessStartedLocked process:" + app.processName
+                    + " startSeq:" + app.startSeq
+                    + " pid:" + pid
+                    + " belongs to another existing app:" + oldApp.processName
+                    + " startSeq:" + oldApp.startSeq);
             mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                     true /*replacingPid*/);
         }
-        mService.mPidsSelfLocked.put(pid, app);
+        mService.mPidsSelfLocked.put(app);
         synchronized (mService.mPidsSelfLocked) {
             if (!procAttached) {
                 Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -2241,7 +2253,7 @@
                 .pendingStart)) {
             int pid = app.pid;
             if (pid > 0) {
-                mService.mPidsSelfLocked.remove(pid);
+                mService.mPidsSelfLocked.remove(app);
                 mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
                 mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
                 if (app.isolated) {
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index b9a6a10..db17f83 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -475,7 +475,7 @@
                                 DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
                                 userId) != 0);
 
-                if (userId == ActivityManager.getCurrentUser()) {
+                if (userId == ActivityManager.getCurrentUser() && !selfChange) {
                     notifyEnabledOnKeyguardCallbacks(userId);
                 }
             } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) {
@@ -494,17 +494,25 @@
         }
 
         boolean getFaceEnabledOnKeyguard() {
-            return mFaceEnabledOnKeyguard.getOrDefault(
-                    ActivityManager.getCurrentUser(), DEFAULT_KEYGUARD_ENABLED);
+            final int user = ActivityManager.getCurrentUser();
+            if (!mFaceEnabledOnKeyguard.containsKey(user)) {
+                onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, user);
+            }
+            return mFaceEnabledOnKeyguard.get(user);
         }
 
         boolean getFaceEnabledForApps(int userId) {
+            if (!mFaceEnabledForApps.containsKey(userId)) {
+                onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
+            }
             return mFaceEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
         }
 
         boolean getFaceAlwaysRequireConfirmation(int userId) {
-            return mFaceAlwaysRequireConfirmation
-                    .getOrDefault(userId, DEFAULT_ALWAYS_REQUIRE_CONFIRMATION);
+            if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) {
+                onChange(true /* selfChange */, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, userId);
+            }
+            return mFaceAlwaysRequireConfirmation.get(userId);
         }
 
         void notifyEnabledOnKeyguardCallbacks(int userId) {
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
index ef94000..388e51f 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
@@ -30,6 +30,7 @@
 import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
+import java.security.spec.InvalidParameterSpecException;
 import java.util.Arrays;
 
 import javax.crypto.BadPaddingException;
@@ -43,6 +44,7 @@
 
 public class SyntheticPasswordCrypto {
     private static final int PROFILE_KEY_IV_SIZE = 12;
+    private static final int DEFAULT_TAG_LENGTH_BITS = 128;
     private static final int AES_KEY_LENGTH = 32; // 256-bit AES key
     private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes();
     // Time between the user credential is verified with GK and the decryption of synthetic password
@@ -60,13 +62,14 @@
         byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length);
         Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                 + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
-        cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
+        cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(DEFAULT_TAG_LENGTH_BITS, iv));
         return cipher.doFinal(ciphertext);
     }
 
     private static byte[] encrypt(SecretKey key, byte[] blob)
             throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
-            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
+            InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
+            InvalidParameterSpecException {
         if (blob == null) {
             return null;
         }
@@ -79,6 +82,11 @@
         if (iv.length != PROFILE_KEY_IV_SIZE) {
             throw new RuntimeException("Invalid iv length: " + iv.length);
         }
+        final GCMParameterSpec spec = cipher.getParameters().getParameterSpec(
+                GCMParameterSpec.class);
+        if (spec.getTLen() != DEFAULT_TAG_LENGTH_BITS) {
+            throw new RuntimeException("Invalid tag length: " + spec.getTLen());
+        }
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         outputStream.write(iv);
         outputStream.write(ciphertext);
@@ -92,7 +100,8 @@
         try {
             return encrypt(key, message);
         } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
-                | IllegalBlockSizeException | BadPaddingException | IOException e) {
+                | IllegalBlockSizeException | BadPaddingException | IOException
+                | InvalidParameterSpecException e) {
             e.printStackTrace();
             return null;
         }
@@ -147,7 +156,7 @@
     public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) {
         try {
             KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
-            keyGenerator.init(new SecureRandom());
+            keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom());
             SecretKey secretKey = keyGenerator.generateKey();
             KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
             keyStore.load(null);
@@ -169,7 +178,8 @@
         } catch (CertificateException | IOException | BadPaddingException
                 | IllegalBlockSizeException
                 | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
-                | InvalidKeyException e) {
+                | InvalidKeyException
+                | InvalidParameterSpecException e) {
             e.printStackTrace();
             throw new RuntimeException("Failed to encrypt blob", e);
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4f85941..13b4ab9 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -23,6 +23,7 @@
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
 import static android.app.Notification.FLAG_NO_CLEAR;
 import static android.app.Notification.FLAG_ONGOING_EVENT;
+import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
 import static android.app.NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED;
 import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED;
 import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED;
@@ -1031,12 +1032,19 @@
                     final StatusBarNotification n = r.sbn;
                     final int callingUid = n.getUid();
                     final String pkg = n.getPackageName();
+                    final boolean wasBubble = r.getNotification().isBubbleNotification();
                     if (isBubble && isNotificationAppropriateToBubble(r, pkg, callingUid,
                             null /* oldEntry */)) {
                         r.getNotification().flags |= FLAG_BUBBLE;
                     } else {
                         r.getNotification().flags &= ~FLAG_BUBBLE;
                     }
+                    if (wasBubble != r.getNotification().isBubbleNotification()) {
+                        // Add the "alert only once" flag so that the notification won't HUN
+                        // unnecessarily just because the bubble flag was changed.
+                        r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
+                        mListeners.notifyPostedLocked(r, r);
+                    }
                 }
             }
         }
@@ -5732,7 +5740,7 @@
         }
         // Suppressed because it's a silent update
         final Notification notification = record.getNotification();
-        if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+        if (record.isUpdate && (notification.flags & FLAG_ONLY_ALERT_ONCE) != 0) {
             return false;
         }
         // Suppressed because another notification in its group handles alerting
@@ -5751,7 +5759,7 @@
     boolean shouldMuteNotificationLocked(final NotificationRecord record) {
         // Suppressed because it's a silent update
         final Notification notification = record.getNotification();
-        if (record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+        if (record.isUpdate && (notification.flags & FLAG_ONLY_ALERT_ONCE) != 0) {
             return true;
         }
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index 7ee167a..99f5839 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -120,42 +120,65 @@
                     return 1;
             }
         }
-        final String packageName = getNextArg();
 
+        final String packageName = getNextArg();
+        if (packageName != null) {
+            List<OverlayInfo> overlaysForTarget = mInterface.getOverlayInfosForTarget(
+                    packageName, userId);
+
+            // If the package is not targeted by any overlays, check if the package is an overlay.
+            if (overlaysForTarget.isEmpty()) {
+                final OverlayInfo info = mInterface.getOverlayInfo(packageName, userId);
+                if (info != null) {
+                    printListOverlay(out, info);
+                }
+                return 0;
+            }
+
+            out.println(packageName);
+
+            // Print the overlays for the target.
+            final int n = overlaysForTarget.size();
+            for (int i = 0; i < n; i++) {
+                printListOverlay(out, overlaysForTarget.get(i));
+            }
+
+            return 0;
+        }
+
+        // Print all overlays grouped by target package name.
         final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
         for (final String targetPackageName : allOverlays.keySet()) {
-            if (targetPackageName.equals(packageName)) {
-                out.println(targetPackageName);
-            }
+            out.println(targetPackageName);
+
             List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName);
             final int n = overlaysForTarget.size();
             for (int i = 0; i < n; i++) {
-                final OverlayInfo oi = overlaysForTarget.get(i);
-                if (!targetPackageName.equals(packageName) && !oi.packageName.equals(packageName)) {
-                    continue;
-                }
-                String status;
-                switch (oi.state) {
-                    case OverlayInfo.STATE_ENABLED_STATIC:
-                    case OverlayInfo.STATE_ENABLED:
-                        status = "[x]";
-                        break;
-                    case OverlayInfo.STATE_DISABLED:
-                        status = "[ ]";
-                        break;
-                    default:
-                        status = "---";
-                        break;
-                }
-                out.println(String.format("%s %s", status, oi.packageName));
+                printListOverlay(out, overlaysForTarget.get(i));
             }
-            if (targetPackageName.equals(packageName)) {
-                out.println();
-            }
+            out.println();
         }
+
         return 0;
     }
 
+    private void printListOverlay(PrintWriter out, OverlayInfo oi) {
+        String status;
+        switch (oi.state) {
+            case OverlayInfo.STATE_ENABLED_STATIC:
+            case OverlayInfo.STATE_ENABLED:
+                status = "[x]";
+                break;
+            case OverlayInfo.STATE_DISABLED:
+                status = "[ ]";
+                break;
+            default:
+                status = "---";
+                break;
+        }
+        out.println(String.format("%s %s", status, oi.packageName));
+    }
+
     private int runEnableDisable(final boolean enable) throws RemoteException {
         final PrintWriter err = getErrPrintWriter();
 
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index fe0b9a6..b7e18c3 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -537,6 +537,7 @@
             Slog.d(TAG, "doAutoBatterySaverLocked: mBootCompleted=" + mBootCompleted
                     + " mSettingsLoaded=" + mSettingsLoaded
                     + " mBatteryStatusSet=" + mBatteryStatusSet
+                    + " mState=" + mState
                     + " mIsBatteryLevelLow=" + mIsBatteryLevelLow
                     + " mIsPowered=" + mIsPowered
                     + " mSettingAutomaticBatterySaver=" + mSettingAutomaticBatterySaver
@@ -689,9 +690,9 @@
                 final boolean isStickyDisabled =
                         mBatterySaverStickyBehaviourDisabled || !mSettingBatterySaverEnabledSticky;
                 if (isStickyDisabled || shouldTurnOffSticky) {
+                    mState = STATE_OFF;
                     setStickyActive(false);
                     triggerStickyDisabledNotification();
-                    mState = STATE_OFF;
                 } else if (!mIsPowered) {
                     // Re-enable BS.
                     enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
@@ -797,7 +798,8 @@
                         Intent.ACTION_POWER_USAGE_SUMMARY));
     }
 
-    private void triggerStickyDisabledNotification() {
+    @VisibleForTesting
+    void triggerStickyDisabledNotification() {
         NotificationManager manager = mContext.getSystemService(NotificationManager.class);
         ensureNotificationChannelExists(manager, BATTERY_SAVER_NOTIF_CHANNEL_ID,
                 R.string.battery_saver_notification_channel_name);
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 1edb93a..7d0da68 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.stats;
 
+import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
 import static android.os.Process.getPidsForCommands;
@@ -33,6 +34,11 @@
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.HistoricalOps;
+import android.app.AppOpsManager.HistoricalOpsRequest;
+import android.app.AppOpsManager.HistoricalPackageOps;
+import android.app.AppOpsManager.HistoricalUidOps;
 import android.app.ProcessMemoryHighWaterMark;
 import android.app.ProcessMemoryState;
 import android.app.StatsManager;
@@ -146,6 +152,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -154,6 +162,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -1941,6 +1950,53 @@
         }
     }
 
+    private void pullAppOps(long elapsedNanos, final long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        long token = Binder.clearCallingIdentity();
+        try {
+            AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+
+            CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
+            HistoricalOpsRequest histOpsRequest =
+                    new HistoricalOpsRequest.Builder(
+                            Instant.now().minus(1, ChronoUnit.HOURS).toEpochMilli(),
+                            Long.MAX_VALUE).build();
+            appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);
+
+            HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
+                    TimeUnit.MILLISECONDS);
+
+            StatsLogEventWrapper e = new StatsLogEventWrapper(StatsLog.APP_OPS, elapsedNanos,
+                    wallClockNanos);
+
+            for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
+                final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
+                final int uid = uidOps.getUid();
+                for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
+                    final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
+                    for (int opIdx = 0; opIdx < packageOps.getOpCount(); opIdx++) {
+                        final AppOpsManager.HistoricalOp op  = packageOps.getOpAt(opIdx);
+                        e.writeInt(uid);
+                        e.writeString(packageOps.getPackageName());
+                        e.writeInt(op.getOpCode());
+                        e.writeLong(op.getForegroundAccessCount(OP_FLAGS_ALL_TRUSTED));
+                        e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_ALL_TRUSTED));
+                        e.writeLong(op.getForegroundRejectCount(OP_FLAGS_ALL_TRUSTED));
+                        e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_ALL_TRUSTED));
+                        e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_ALL_TRUSTED));
+                        e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_ALL_TRUSTED));
+                        pulledData.add(e);
+                    }
+                }
+            }
+        } catch (Throwable t) {
+            Log.e(TAG, "Could not read appops", t);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+
     /**
      * Add a RoleHolder atom for each package that holds a role.
      *
@@ -2331,6 +2387,10 @@
                 pullFaceSettings(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.APP_OPS: {
+                pullAppOps(elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/core/java/com/android/server/updates/ConversationActionsInstallReceiver.java b/services/core/java/com/android/server/updates/ConversationActionsInstallReceiver.java
index 7310af3..bbe534e 100644
--- a/services/core/java/com/android/server/updates/ConversationActionsInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/ConversationActionsInstallReceiver.java
@@ -25,4 +25,9 @@
                 "metadata/actions_suggestions",
                 "version");
     }
+
+    @Override
+    protected boolean verifyVersion(int current, int alternative) {
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/updates/LangIdInstallReceiver.java b/services/core/java/com/android/server/updates/LangIdInstallReceiver.java
index 05dad21..ecfa3aa 100644
--- a/services/core/java/com/android/server/updates/LangIdInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/LangIdInstallReceiver.java
@@ -25,4 +25,9 @@
             "metadata/lang_id",
             "version");
     }
+
+    @Override
+    protected boolean verifyVersion(int current, int alternative) {
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 1344727..66b305e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1085,6 +1085,22 @@
         if (root == this) {
             task.setRootProcess(proc);
         }
+        // Override the process configuration to match the display where the first activity in
+        // the process was launched. This can help with compat issues on secondary displays when
+        // apps use Application to obtain configuration or metrics instead of Activity.
+        final ActivityDisplay display = getDisplay();
+        if (display == null || display.mDisplayId == INVALID_DISPLAY) {
+            return;
+        }
+        if (!proc.hasActivities() && display.mDisplayId != DEFAULT_DISPLAY) {
+            proc.registerDisplayConfigurationListenerLocked(display);
+        } else if (display.mDisplayId == DEFAULT_DISPLAY) {
+            // Once an activity is launched on default display - stop listening for other displays
+            // configurations to maintain compatibility with previous platform releases. E.g. when
+            // an activity is launched in a Bubble and then moved to default screen, we should match
+            // the global device config.
+            proc.unregisterDisplayConfigurationListenerLocked();
+        }
     }
 
     boolean hasProcess() {
@@ -3233,7 +3249,7 @@
         // Update last reported values.
         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
 
-        setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
+        setLastReportedConfiguration(getProcessGlobalConfiguration(), newMergedOverrideConfig);
 
         if (mState == INITIALIZING) {
             // No need to relaunch or schedule new config for activity that hasn't been launched
@@ -3342,6 +3358,14 @@
         return true;
     }
 
+    /** Get process configuration, or global config if the process is not set. */
+    private Configuration getProcessGlobalConfiguration() {
+        if (app != null) {
+            return app.getConfiguration();
+        }
+        return mAtmService.getGlobalConfiguration();
+    }
+
     /**
      * When assessing a configuration change, decide if the changes flags and the new configurations
      * should cause the Activity to relaunch.
@@ -3449,7 +3473,7 @@
             mStackSupervisor.activityRelaunchingLocked(this);
             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                     pendingNewIntents, configChangeFlags,
-                    new MergedConfiguration(mAtmService.getGlobalConfiguration(),
+                    new MergedConfiguration(getProcessGlobalConfiguration(),
                             getMergedOverrideConfiguration()),
                     preserveWindow);
             final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1cdb49d..9d08e10 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -280,13 +280,6 @@
             mActivityOptions = ActivityOptions.makeBasic();
         }
 
-        ActivityRecord homeActivityRecord = mRootActivityContainer.getDefaultDisplayHomeActivity();
-        if (homeActivityRecord != null && homeActivityRecord.getTaskRecord() != null) {
-            // Showing credential confirmation activity in home task to avoid stopping
-            // multi-windowed mode after showing the full-screen credential confirmation activity.
-            mActivityOptions.setLaunchTaskId(homeActivityRecord.getTaskRecord().taskId);
-        }
-
         final UserInfo parent = mUserManager.getProfileParent(mUserId);
         mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id, 0, mRealCallingUid);
         mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 89962a5..772e5e6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -39,7 +39,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.ApplicationInfo.FLAG_FACTORY_TEST;
 import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
@@ -6892,15 +6891,9 @@
             synchronized (mGlobalLock) {
                 final long ident = Binder.clearCallingIdentity();
                 try {
-                    intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
-                            FLAG_ACTIVITY_TASK_ON_HOME);
-                    ActivityOptions activityOptions = options != null
+                    intent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                    final ActivityOptions activityOptions = options != null
                             ? new ActivityOptions(options) : ActivityOptions.makeBasic();
-                    final ActivityRecord homeActivity =
-                            mRootActivityContainer.getDefaultDisplayHomeActivity();
-                    if (homeActivity != null) {
-                        activityOptions.setLaunchTaskId(homeActivity.getTaskRecord().taskId);
-                    }
                     mContext.startActivityAsUser(intent, activityOptions.toBundle(),
                             UserHandle.CURRENT);
                 } finally {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ecbecba..3d7e50d 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -2782,6 +2782,7 @@
     protected void onAnimationFinished() {
         super.onAnimationFinished();
 
+        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#onAnimationFinished");
         mTransit = TRANSIT_UNSET;
         mTransitFlags = 0;
         mNeedsZBoost = false;
@@ -2816,6 +2817,7 @@
         scheduleAnimation();
 
         mActivityRecord.onAnimationFinished();
+        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1e826ee..82ea4fe 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1480,7 +1480,7 @@
         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
         // By updating the Display info here it will be available to
         // #computeScreenConfiguration() later.
-        updateDisplayAndOrientation(getConfiguration().uiMode);
+        updateDisplayAndOrientation(getConfiguration().uiMode, null /* outConfig */);
 
         // NOTE: We disable the rotation in the emulator because
         //       it doesn't support hardware OpenGL emulation yet.
@@ -1578,7 +1578,7 @@
      * changed.
      * Do not call if {@link WindowManagerService#mDisplayReady} == false.
      */
-    private DisplayInfo updateDisplayAndOrientation(int uiMode) {
+    private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) {
         // Use the effective "visual" dimensions based on current rotation
         final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
         final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
@@ -1610,6 +1610,9 @@
             mDisplayInfo.flags &= ~Display.FLAG_SCALING_DISABLED;
         }
 
+        computeSizeRangesAndScreenLayout(mDisplayInfo, rotated, uiMode, dw, dh,
+                mDisplayMetrics.density, outConfig);
+
         // We usually set the override info in DisplayManager so that we get consistent display
         // metrics values when displays are changing and don't send out new values until WM is aware
         // of them. However, we don't do this for displays that serve as containers for ActivityView
@@ -1658,7 +1661,7 @@
      * Do not call if mDisplayReady == false.
      */
     void computeScreenConfiguration(Configuration config) {
-        final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
+        final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
         calculateBounds(displayInfo, mTmpBounds);
         config.windowConfiguration.setBounds(mTmpBounds);
 
@@ -1688,9 +1691,6 @@
         final boolean rotated = (displayInfo.rotation == Surface.ROTATION_90
                 || displayInfo.rotation == Surface.ROTATION_270);
 
-        computeSizeRangesAndScreenLayout(displayInfo, rotated, config.uiMode, dw, dh, density,
-                config);
-
         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
                 ? Configuration.SCREENLAYOUT_ROUND_YES
@@ -1844,6 +1844,10 @@
         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, uiMode, unrotDh, unrotDw);
         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, uiMode, unrotDw, unrotDh);
         adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, uiMode, unrotDh, unrotDw);
+
+        if (outConfig == null) {
+            return;
+        }
         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
                 displayInfo.displayCutout);
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index ef2a21d..b30da5e 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -819,7 +819,7 @@
         } catch (Settings.SettingNotFoundException e) {
             // Log to SafetyNet for b/127605586
             android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, "");
-            return mLockPatternUtils.isSecure(USER_CURRENT);
+            return getLockPatternUtils().isSecure(USER_CURRENT);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ab5e071..d838691 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -319,7 +319,8 @@
      * Sets the bounds animation target bounds ahead of an animation.  This can't currently be done
      * in onAnimationStart() since that is started on the UiThread.
      */
-    void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds, boolean toFullscreen) {
+    private void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds,
+            boolean toFullscreen) {
         mBoundsAnimatingRequested = true;
         mBoundsAnimatingToFullscreen = toFullscreen;
         if (destBounds != null) {
@@ -329,7 +330,11 @@
         }
         if (sourceHintBounds != null) {
             mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
-        } else {
+        } else if (!mBoundsAnimating) {
+            // If the bounds are already animating, we don't want to reset the source hint. This is
+            // because the source hint is sent when starting the animation from the client that
+            // requested to enter pip. Other requests can adjust the pip bounds during an animation,
+            // but could accidentally reset the source hint bounds.
             mBoundsAnimationSourceHintBounds.setEmpty();
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 12b62b9..5fc3997 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -439,7 +439,10 @@
 
     @Override
     protected ConfigurationContainer getParent() {
-        return null;
+        // Returning RootActivityContainer as the parent, so that this process controller always
+        // has full configuration and overrides (e.g. from display) are always added on top of
+        // global config.
+        return mAtm.mRootActivityContainer;
     }
 
     @HotPath(caller = HotPath.PROCESS_CHANGE)
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5ef184a..c35e866 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3104,7 +3104,7 @@
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
                     + ": " + mWindowFrames.mCompatFrame);
             final MergedConfiguration mergedConfiguration =
-                    new MergedConfiguration(mWmService.mRoot.getConfiguration(),
+                    new MergedConfiguration(getProcessGlobalConfiguration(),
                     getMergedOverrideConfiguration());
 
             setLastReportedMergedConfiguration(mergedConfiguration);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index fb34913..1ab3b98 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -349,7 +349,7 @@
                 lastPos++;
             } else {
                 // Two events have the same timestamp, check if they are the same.
-                if (lastEvent.equals(curEvent)) {
+                if (lastEvent.eventEquals(curEvent)) {
                     // Actual overlap, just skip the event.
                     if (DEBUG) Slog.d(TAG, "Skipped dup event with timestamp: " + lastNanos);
                 } else {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2b5cd01..e42ed3b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1049,12 +1049,7 @@
             mDisplayManagerService.windowManagerAndInputReady();
             traceEnd();
 
-            // Skip Bluetooth if we have an emulator kernel
-            // TODO: Use a more reliable check to see if this product should
-            // support Bluetooth - see bug 988521
-            if (isEmulator) {
-                Slog.i(TAG, "No Bluetooth Service (emulator)");
-            } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
+            if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else if (!context.getPackageManager().hasSystemFeature
                     (PackageManager.FEATURE_BLUETOOTH)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 6517303..77e2517 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -43,6 +43,8 @@
 import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL;
 import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY;
 import static com.android.server.AlarmManagerService.Constants.KEY_MIN_INTERVAL;
+import static com.android.server.AlarmManagerService.IS_WAKEUP_MASK;
+import static com.android.server.AlarmManagerService.TIME_CHANGED_MASK;
 import static com.android.server.AlarmManagerService.WORKING_INDEX;
 
 import static org.junit.Assert.assertEquals;
@@ -126,13 +128,15 @@
     private MockitoSession mMockingSession;
     private Injector mInjector;
     private volatile long mNowElapsedTest;
+    private volatile long mNowRtcTest;
     @GuardedBy("mTestTimer")
     private TestTimer mTestTimer = new TestTimer();
 
     static class TestTimer {
         private long mElapsed;
         boolean mExpired;
-        int mType;
+        private int mType;
+        private int mFlags; // Flags used to decide what needs to be evaluated.
 
         synchronized long getElapsed() {
             return mElapsed;
@@ -147,7 +151,16 @@
             return mType;
         }
 
+        synchronized int getFlags() {
+            return mFlags;
+        }
+
         synchronized void expire() throws InterruptedException {
+            expire(IS_WAKEUP_MASK); // Default: evaluate eligibility of all alarms
+        }
+
+        synchronized void expire(int flags) throws InterruptedException {
+            mFlags = flags;
             mExpired = true;
             notifyAll();
             // Now wait for the alarm thread to finish execution.
@@ -181,7 +194,7 @@
                 }
                 mTestTimer.mExpired = false;
             }
-            return AlarmManagerService.IS_WAKEUP_MASK; // Doesn't matter, just evaluate.
+            return mTestTimer.getFlags();
         }
 
         @Override
@@ -215,6 +228,11 @@
         }
 
         @Override
+        long getCurrentTimeMillis() {
+            return mNowRtcTest;
+        }
+
+        @Override
         AlarmManagerService.ClockReceiver getClockReceiver(AlarmManagerService service) {
             return mClockReceiver;
         }
@@ -340,7 +358,7 @@
     }
 
     @Test
-    public void testSingleAlarmSet() {
+    public void singleElapsedAlarmSet() {
         final long triggerTime = mNowElapsedTest + 5000;
         final PendingIntent alarmPi = getNewMockPendingIntent();
         setTestAlarm(ELAPSED_REALTIME_WAKEUP, triggerTime, alarmPi);
@@ -348,6 +366,33 @@
     }
 
     @Test
+    public void singleRtcAlarmSet() {
+        mNowElapsedTest = 54;
+        mNowRtcTest = 1243;     // arbitrary values of time
+        final long triggerRtc = mNowRtcTest + 5000;
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi);
+        final long triggerElapsed = triggerRtc - (mNowRtcTest - mNowElapsedTest);
+        assertEquals(triggerElapsed, mTestTimer.getElapsed());
+    }
+
+    @Test
+    public void timeChangeMovesRtcAlarm() throws Exception {
+        mNowElapsedTest = 42;
+        mNowRtcTest = 4123;     // arbitrary values of time
+        final long triggerRtc = mNowRtcTest + 5000;
+        final PendingIntent alarmPi = getNewMockPendingIntent();
+        setTestAlarm(RTC_WAKEUP, triggerRtc, alarmPi);
+        final long triggerElapsed1 = mTestTimer.getElapsed();
+        final long timeDelta = -123;
+        mNowRtcTest += timeDelta;
+        mTestTimer.expire(TIME_CHANGED_MASK);
+        final long triggerElapsed2 = mTestTimer.getElapsed();
+        assertEquals("Invalid movement of triggerElapsed following time change", triggerElapsed2,
+                triggerElapsed1 - timeDelta);
+    }
+
+    @Test
     public void testSingleAlarmExpiration() throws Exception {
         final long triggerTime = mNowElapsedTest + 5000;
         final PendingIntent alarmPi = getNewMockPendingIntent();
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index 212d2a8..a8faa54 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -15,6 +15,10 @@
  */
 package com.android.server.power.batterysaver;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -22,6 +26,8 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.NotificationManager;
@@ -37,6 +43,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.InOrder;
 
 import java.util.HashMap;
 import java.util.Objects;
@@ -201,6 +208,8 @@
         mDevice = new Device();
 
         mTarget = new TestableBatterySaverStateMachine();
+        spyOn(mTarget);
+        doNothing().when(mTarget).triggerStickyDisabledNotification();
 
         mDevice.pushBatteryStatus();
         mTarget.onBootCompleted();
@@ -423,7 +432,7 @@
         assertEquals(70, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
 
-        // Bump ump the threshold.
+        // Bump up the threshold.
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 70);
         mDevice.setBatteryLevel(mPersistedState.batteryLevel);
 
@@ -545,6 +554,8 @@
 
     @Test
     public void testAutoBatterySaver_withSticky_withAutoOffEnabled() {
+        InOrder inOrder = inOrder(mTarget);
+
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1);
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90);
@@ -569,6 +580,7 @@
         assertEquals(true, mDevice.batterySaverEnabled); // Stays on.
         assertEquals(95, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        inOrder.verify(mTarget, never()).triggerStickyDisabledNotification();
 
         // Scenario 2: User turns BS on manually above the threshold then charges device. BS
         // shouldn't turn back on.
@@ -584,6 +596,7 @@
         assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled.
         assertEquals(97, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        inOrder.verify(mTarget).triggerStickyDisabledNotification();
 
         // Scenario 3: User turns BS on manually above the threshold. Device drains below
         // threshold and then charged to below threshold. Sticky BS should activate.
@@ -612,6 +625,7 @@
         assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(30, mPersistedState.batteryLevel);
         assertEquals(true, mPersistedState.batteryLow);
+        inOrder.verify(mTarget, never()).triggerStickyDisabledNotification();
 
         // Scenario 4: User turns BS on manually above the threshold. Device drains below
         // threshold and is eventually charged to above threshold. Sticky BS should turn off.
@@ -627,6 +641,7 @@
         assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled.
         assertEquals(90, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        inOrder.verify(mTarget).triggerStickyDisabledNotification();
 
         // Scenario 5: User turns BS on manually below threshold and charges to below threshold.
         // Sticky BS should activate.
@@ -654,6 +669,7 @@
         assertEquals(true, mDevice.batterySaverEnabled); // Sticky BS still on.
         assertEquals(80, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        inOrder.verify(mTarget, never()).triggerStickyDisabledNotification();
 
         // Scenario 6: User turns BS on manually below threshold and eventually charges to above
         // threshold. Sticky BS should turn off.
@@ -665,6 +681,7 @@
         assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(95, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        inOrder.verify(mTarget).triggerStickyDisabledNotification();
 
         // Scenario 7: User turns BS on above threshold and then reboots device. Sticky BS
         // shouldn't activate.
@@ -676,6 +693,8 @@
         assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(93, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        // initDevice() changes the mTarget reference, so inOrder is invalid here.
+        verify(mTarget).triggerStickyDisabledNotification();
 
         // Scenario 8: User turns BS on below threshold and then reboots device without charging.
         // Sticky BS should activate.
@@ -690,6 +709,8 @@
         assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(75, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        // initDevice() changes the mTarget reference, so inOrder is invalid here.
+        verify(mTarget, never()).triggerStickyDisabledNotification();
 
         // Scenario 9: User turns BS on below threshold and then reboots device after charging
         // above threshold. Sticky BS shouldn't activate.
@@ -702,6 +723,8 @@
         assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(100, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        // initDevice() changes the mTarget reference, so inOrder is invalid here.
+        verify(mTarget).triggerStickyDisabledNotification();
 
         // Scenario 10: Somehow autoDisableLevel is set to a value below lowPowerModeTriggerLevel
         // and then user enables manually above both thresholds, discharges below
@@ -738,6 +761,8 @@
         assertEquals(true, mDevice.batterySaverEnabled);
         assertEquals(65, mPersistedState.batteryLevel);
         assertEquals(true, mPersistedState.batteryLow);
+        // initDevice() changes the mTarget reference, so inOrder is invalid here.
+        verify(mTarget, never()).triggerStickyDisabledNotification();
     }
 
     @Test
@@ -780,6 +805,7 @@
         assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled.
         assertEquals(95, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
+        verify(mTarget).triggerStickyDisabledNotification();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 09e20e0..1f5ebe4 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -235,6 +235,10 @@
         mPasswordSlotManager.cleanup();
     }
 
+    protected void flushHandlerTasks() {
+        mService.mHandler.runWithScissors(() -> { }, 0 /*now*/); // Flush runnables on handler
+    }
+
     protected void assertNotEquals(long expected, long actual) {
         assertTrue(expected != actual);
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 19ed5f3..f85e2cc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -163,5 +163,4 @@
         }
         return storedData;
     }
-
 }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 0273f76..1cd590c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -232,7 +232,7 @@
 
         reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
-        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        flushHandlerTasks();
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
 
@@ -242,7 +242,7 @@
 
         reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
-        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        flushHandlerTasks();
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
 
@@ -254,7 +254,7 @@
 
         reset(mAuthSecretService);
         mService.onUnlockUser(PRIMARY_USER_ID);
-        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        flushHandlerTasks();
         verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
     }
 
@@ -357,7 +357,7 @@
                 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
         // Verify DPM gets notified about new device lock
-        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        flushHandlerTasks();
         final PasswordMetrics metric = PasswordMetrics.computeForCredential(
                 LockPatternUtils.CREDENTIAL_TYPE_PATTERN, pattern);
         verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
@@ -384,6 +384,7 @@
 
         mLocalService.setLockCredentialWithToken(null, LockPatternUtils.CREDENTIAL_TYPE_NONE,
                 handle, token, PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        flushHandlerTasks(); // flush the unlockUser() call before changing password again
         mLocalService.setLockCredentialWithToken(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 handle, token, PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index d2332bf..3661e89 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -22,6 +22,7 @@
 import static android.app.Notification.CATEGORY_CALL;
 import static android.app.Notification.FLAG_BUBBLE;
 import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
+import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
 import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -119,7 +120,6 @@
 import android.service.notification.Adjustment;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
-import android.service.notification.NotifyingApp;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenPolicy;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -165,10 +165,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.function.Consumer;
 
 @SmallTest
@@ -5012,6 +5010,9 @@
                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
         waitForIdle();
 
+        // Reset as this is called when the notif is first sent
+        reset(mListeners);
+
         // First we were a bubble
         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
         assertEquals(1, notifsBefore.length);
@@ -5021,10 +5022,13 @@
         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
         waitForIdle();
 
-        // Now we are not a bubble
-        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
-        assertEquals(1, notifsAfter.length);
-        assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
+        // Make sure we are not a bubble / reported as such to listeners
+        ArgumentCaptor<NotificationRecord> captor =
+                ArgumentCaptor.forClass(NotificationRecord.class);
+        verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
+
+        assertEquals((captor.getValue().getNotification().flags & FLAG_BUBBLE), 0);
+        assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0);
     }
 
     @Test
@@ -5054,14 +5058,20 @@
         when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
                 IMPORTANCE_FOREGROUND);
 
+        // Reset as this is called when the notif is first sent
+        reset(mListeners);
+
         // Notify we are now a bubble
         mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
         waitForIdle();
 
-        // Make sure we are a bubble
-        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
-        assertEquals(1, notifsAfter.length);
-        assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
+        // Make sure we are a bubble / reported as such to listeners
+        ArgumentCaptor<NotificationRecord> captor =
+                ArgumentCaptor.forClass(NotificationRecord.class);
+        verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
+
+        assertTrue((captor.getValue().getNotification().flags & FLAG_BUBBLE) != 0);
+        assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0);
     }
 
     @Test
@@ -5082,6 +5092,9 @@
                 nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
         waitForIdle();
 
+        // Reset as this is called when the notif is first sent
+        reset(mListeners);
+
         // Would be a normal notification because wouldn't have met requirements to bubble
         StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
         assertEquals(1, notifsBefore.length);
@@ -5095,6 +5108,7 @@
         StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
         assertEquals(1, notifsAfter.length);
         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
+        verify(mListeners, times(0)).notifyPostedLocked(any(), any());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 11a177a..f8fd64a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_90;
@@ -38,6 +40,7 @@
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -56,10 +59,10 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.util.MergedConfiguration;
 import android.util.MutableBoolean;
+import android.view.DisplayInfo;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner.Stub;
 import android.view.RemoteAnimationAdapter;
@@ -598,6 +601,67 @@
         assertNull(mActivity.pendingOptions);
     }
 
+    @Test
+    public void testSetProcessOverridesConfig() {
+        final ActivityRecord defaultDisplayActivity =
+                createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
+        assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
+
+        final ActivityRecord secondaryDisplayActivity =
+                createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
+        assertTrue(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
+        assertEquals(secondaryDisplayActivity.getDisplay().getResolvedOverrideConfiguration(),
+                secondaryDisplayActivity.app.getRequestedOverrideConfiguration());
+
+        assertNotEquals(defaultDisplayActivity.getConfiguration(),
+                secondaryDisplayActivity.getConfiguration());
+    }
+
+    @Test
+    public void testSetProcessDoesntOverrideConfigIfAnotherActivityPresent() {
+        final ActivityRecord defaultDisplayActivity =
+                createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
+        assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
+
+        final ActivityRecord secondaryDisplayActivity =
+                createActivityOnDisplay(false /* defaultDisplay */, defaultDisplayActivity.app);
+        assertFalse(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
+    }
+
+    @Test
+    public void testActivityOnDefaultDisplayClearsProcessOverride() {
+        final ActivityRecord secondaryDisplayActivity =
+                createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
+        assertTrue(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
+
+        final ActivityRecord defaultDisplayActivity =
+                createActivityOnDisplay(true /* defaultDisplay */,
+                        secondaryDisplayActivity.app);
+        assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
+        assertFalse(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
+    }
+
+    /**
+     * Creates an activity on display. For non-default display request it will also create a new
+     * display with custom DisplayInfo.
+     */
+    private ActivityRecord createActivityOnDisplay(boolean defaultDisplay,
+            WindowProcessController process) {
+        final ActivityDisplay display;
+        if (defaultDisplay) {
+            display = mRootActivityContainer.getDefaultDisplay();
+        } else {
+            final DisplayInfo info = new DisplayInfo();
+            info.logicalWidth = 100;
+            info.logicalHeight = 100;
+            display = addNewActivityDisplayAt(info, POSITION_TOP);
+        }
+        final TestActivityStack stack = display.createStack(WINDOWING_MODE_UNDEFINED,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+        return new ActivityBuilder(mService).setTask(task).setUseProcess(process).build();
+    }
+
     /** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */
     private void prepareFixedAspectRatioUnresizableActivity() {
         setupDisplayContentForCompatDisplayInsets();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 53b0add..d8c0de7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -195,6 +195,7 @@
         private ActivityStack mStack;
         private int mActivityFlags;
         private int mLaunchMode;
+        private WindowProcessController mWpc;
 
         ActivityBuilder(ActivityTaskManagerService service) {
             mService = service;
@@ -245,6 +246,11 @@
             return this;
         }
 
+        ActivityBuilder setUseProcess(WindowProcessController wpc) {
+            mWpc = wpc;
+            return this;
+        }
+
         ActivityRecord build() {
             if (mComponent == null) {
                 final int id = sCurrentActivityId++;
@@ -290,12 +296,18 @@
                 mTaskRecord.addActivityToTop(activity);
             }
 
-            final WindowProcessController wpc = new WindowProcessController(mService,
-                    mService.mContext.getApplicationInfo(), "name", 12345,
-                    UserHandle.getUserId(12345), mock(Object.class),
-                    mock(WindowProcessListener.class));
-            wpc.setThread(mock(IApplicationThread.class));
+            final WindowProcessController wpc;
+            if (mWpc != null) {
+                wpc = mWpc;
+            } else {
+                wpc = new WindowProcessController(mService,
+                        mService.mContext.getApplicationInfo(), "name", 12345,
+                        UserHandle.getUserId(12345), mock(Object.class),
+                        mock(WindowProcessListener.class));
+                wpc.setThread(mock(IApplicationThread.class));
+            }
             activity.setProcess(wpc);
+            wpc.addActivityIfNeeded(activity);
             return activity;
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index fe45411..8528954 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -153,7 +153,6 @@
     @FlakyTest(bugId = 131005232)
     public void testLandscapeSeascapeRotationByApp() {
         // Some plumbing to get the service ready for rotation updates.
-        mWm.mDisplayReady = true;
         mWm.mDisplayEnabled = true;
 
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
@@ -186,7 +185,6 @@
     @Test
     public void testLandscapeSeascapeRotationByPolicy() {
         // Some plumbing to get the service ready for rotation updates.
-        mWm.mDisplayReady = true;
         mWm.mDisplayEnabled = true;
 
         final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
@@ -379,6 +377,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 131176283)
     public void testCreateRemoveStartingWindow() {
         mToken.addStartingWindow(mPackageName,
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 366acea..427a929 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -41,6 +41,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.hardware.display.DisplayManagerInternal;
 import android.net.Uri;
@@ -175,6 +176,12 @@
         // Display creation is driven by the ActivityManagerService via
         // ActivityStackSupervisor. We emulate those steps here.
         mWindowManagerService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class));
+        mWindowManagerService.displayReady();
+
+        final Configuration defaultDisplayConfig =
+                mWindowManagerService.computeNewConfiguration(DEFAULT_DISPLAY);
+        doReturn(defaultDisplayConfig).when(atms).getGlobalConfiguration();
+        doReturn(defaultDisplayConfig).when(atms).getGlobalConfigurationForPid(anyInt());
 
         mMockTracker.stopTracking();
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index a7c84a1..7b8fba0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -26,7 +26,9 @@
 import static org.mockito.Mockito.mock;
 
 import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
 import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
 
 import org.junit.Test;
 
@@ -78,6 +80,26 @@
         assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
     }
 
+    @Test
+    public void testConfigurationForSecondaryScreen() {
+        final WindowProcessController wpc = new WindowProcessController(
+                mService, mock(ApplicationInfo.class), null, 0, -1, null, null);
+        //By default, the process should not listen to any display.
+        assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
+
+        // Register to a new display as a listener.
+        final DisplayInfo info = new DisplayInfo();
+        info.logicalWidth = 100;
+        info.logicalHeight = 100;
+        TestActivityDisplay display = addNewActivityDisplayAt(info, WindowContainer.POSITION_TOP);
+        wpc.registerDisplayConfigurationListenerLocked(display);
+
+        assertEquals(display.mDisplayId, wpc.getDisplayId());
+        final Configuration expectedConfig = mService.mRootActivityContainer.getConfiguration();
+        expectedConfig.updateFrom(display.getConfiguration());
+        assertEquals(expectedConfig, wpc.getConfiguration());
+    }
+
     private TestActivityDisplay createTestActivityDisplayInContainer() {
         final TestActivityDisplay testActivityDisplay = createNewActivityDisplay();
         mRootActivityContainer.addChild(testActivityDisplay, POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 3a702cb9..de28b5f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -154,7 +154,6 @@
             context.getDisplay().getDisplayInfo(mDisplayInfo);
             mDisplayContent = createNewDisplay();
             mWm.mDisplayEnabled = true;
-            mWm.mDisplayReady = true;
 
             // Set-up some common windows.
             mCommonWindows = new HashSet<>();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index eefaf47..be4729a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1249,6 +1249,7 @@
      * @deprecated Use
      * {@link android.app.role.RoleManager#addRoleHolderAsUser(String, String, int, UserHandle,
      * Executor, java.util.function.Consumer)} instead.
+     * @removed
      */
     @SystemApi
     @Deprecated
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 14ae689..9d732ba 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntRange;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
@@ -46,7 +47,7 @@
     private int mRssi; // in dBm [-113, -51] or UNAVAILABLE
     @UnsupportedAppUsage
     private int mBitErrorRate; // bit error rate (0-7, 99) TS 27.007 8.5 or UNAVAILABLE
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private int mTimingAdvance; // range from 0-219 or CellInfo.UNAVAILABLE if unknown
     private int mLevel;
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 1551ce3..984d8f7 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -337,7 +337,7 @@
      * Reference: 3GPP TS 36.104 5.4.3 */
     private int mLteEarfcnRsrpBoost = 0;
 
-    private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
+    private final List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
 
     private String mOperatorAlphaLongRaw;
     private String mOperatorAlphaShortRaw;
@@ -420,8 +420,10 @@
         mCellBandwidths = s.mCellBandwidths == null ? null :
                 Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
         mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
-        mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null :
-                s.getNetworkRegistrationInfoList();
+        synchronized (mNetworkRegistrationInfos) {
+            mNetworkRegistrationInfos.clear();
+            mNetworkRegistrationInfos.addAll(s.getNetworkRegistrationInfoList());
+        }
         mNrFrequencyRange = s.mNrFrequencyRange;
         mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
         mOperatorAlphaShortRaw = s.mOperatorAlphaShortRaw;
@@ -453,8 +455,9 @@
         mCdmaEriIconMode = in.readInt();
         mIsEmergencyOnly = in.readInt() != 0;
         mLteEarfcnRsrpBoost = in.readInt();
-        mNetworkRegistrationInfos = new ArrayList<>();
-        in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
+        synchronized (mNetworkRegistrationInfos) {
+            in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
+        }
         mChannelNumber = in.readInt();
         mCellBandwidths = in.createIntArray();
         mNrFrequencyRange = in.readInt();
@@ -481,7 +484,9 @@
         out.writeInt(mCdmaEriIconMode);
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
         out.writeInt(mLteEarfcnRsrpBoost);
-        out.writeList(mNetworkRegistrationInfos);
+        synchronized (mNetworkRegistrationInfos) {
+            out.writeList(mNetworkRegistrationInfos);
+        }
         out.writeInt(mChannelNumber);
         out.writeIntArray(mCellBandwidths);
         out.writeInt(mNrFrequencyRange);
@@ -823,31 +828,33 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(
-                mVoiceRegState,
-                mDataRegState,
-                mChannelNumber,
-                Arrays.hashCode(mCellBandwidths),
-                mVoiceOperatorAlphaLong,
-                mVoiceOperatorAlphaShort,
-                mVoiceOperatorNumeric,
-                mDataOperatorAlphaLong,
-                mDataOperatorAlphaShort,
-                mDataOperatorNumeric,
-                mIsManualNetworkSelection,
-                mCssIndicator,
-                mNetworkId,
-                mSystemId,
-                mCdmaRoamingIndicator,
-                mCdmaDefaultRoamingIndicator,
-                mCdmaEriIconIndex,
-                mCdmaEriIconMode,
-                mIsEmergencyOnly,
-                mLteEarfcnRsrpBoost,
-                mNetworkRegistrationInfos,
-                mNrFrequencyRange,
-                mOperatorAlphaLongRaw,
-                mOperatorAlphaShortRaw);
+        synchronized (mNetworkRegistrationInfos) {
+            return Objects.hash(
+                    mVoiceRegState,
+                    mDataRegState,
+                    mChannelNumber,
+                    Arrays.hashCode(mCellBandwidths),
+                    mVoiceOperatorAlphaLong,
+                    mVoiceOperatorAlphaShort,
+                    mVoiceOperatorNumeric,
+                    mDataOperatorAlphaLong,
+                    mDataOperatorAlphaShort,
+                    mDataOperatorNumeric,
+                    mIsManualNetworkSelection,
+                    mCssIndicator,
+                    mNetworkId,
+                    mSystemId,
+                    mCdmaRoamingIndicator,
+                    mCdmaDefaultRoamingIndicator,
+                    mCdmaEriIconIndex,
+                    mCdmaEriIconMode,
+                    mIsEmergencyOnly,
+                    mLteEarfcnRsrpBoost,
+                    mNetworkRegistrationInfos,
+                    mNrFrequencyRange,
+                    mOperatorAlphaLongRaw,
+                    mOperatorAlphaShortRaw);
+        }
     }
 
     @Override
@@ -855,30 +862,31 @@
         if (!(o instanceof ServiceState)) return false;
         ServiceState s = (ServiceState) o;
 
-        return mVoiceRegState == s.mVoiceRegState
-                && mDataRegState == s.mDataRegState
-                && mIsManualNetworkSelection == s.mIsManualNetworkSelection
-                && mChannelNumber == s.mChannelNumber
-                && Arrays.equals(mCellBandwidths, s.mCellBandwidths)
-                && equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
-                && equalsHandlesNulls(mVoiceOperatorAlphaShort, s.mVoiceOperatorAlphaShort)
-                && equalsHandlesNulls(mVoiceOperatorNumeric, s.mVoiceOperatorNumeric)
-                && equalsHandlesNulls(mDataOperatorAlphaLong, s.mDataOperatorAlphaLong)
-                && equalsHandlesNulls(mDataOperatorAlphaShort, s.mDataOperatorAlphaShort)
-                && equalsHandlesNulls(mDataOperatorNumeric, s.mDataOperatorNumeric)
-                && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
-                && equalsHandlesNulls(mNetworkId, s.mNetworkId)
-                && equalsHandlesNulls(mSystemId, s.mSystemId)
-                && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
-                && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
-                        s.mCdmaDefaultRoamingIndicator)
-                && mIsEmergencyOnly == s.mIsEmergencyOnly
-                && equalsHandlesNulls(mOperatorAlphaLongRaw, s.mOperatorAlphaLongRaw)
-                && equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
-                && (mNetworkRegistrationInfos == null
-                ? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
-                && mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
-                && mNrFrequencyRange == s.mNrFrequencyRange;
+        synchronized (mNetworkRegistrationInfos) {
+            return mVoiceRegState == s.mVoiceRegState
+                    && mDataRegState == s.mDataRegState
+                    && mIsManualNetworkSelection == s.mIsManualNetworkSelection
+                    && mChannelNumber == s.mChannelNumber
+                    && Arrays.equals(mCellBandwidths, s.mCellBandwidths)
+                    && equalsHandlesNulls(mVoiceOperatorAlphaLong, s.mVoiceOperatorAlphaLong)
+                    && equalsHandlesNulls(mVoiceOperatorAlphaShort, s.mVoiceOperatorAlphaShort)
+                    && equalsHandlesNulls(mVoiceOperatorNumeric, s.mVoiceOperatorNumeric)
+                    && equalsHandlesNulls(mDataOperatorAlphaLong, s.mDataOperatorAlphaLong)
+                    && equalsHandlesNulls(mDataOperatorAlphaShort, s.mDataOperatorAlphaShort)
+                    && equalsHandlesNulls(mDataOperatorNumeric, s.mDataOperatorNumeric)
+                    && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
+                    && equalsHandlesNulls(mNetworkId, s.mNetworkId)
+                    && equalsHandlesNulls(mSystemId, s.mSystemId)
+                    && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
+                    && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
+                    s.mCdmaDefaultRoamingIndicator)
+                    && mIsEmergencyOnly == s.mIsEmergencyOnly
+                    && equalsHandlesNulls(mOperatorAlphaLongRaw, s.mOperatorAlphaLongRaw)
+                    && equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
+                    && mNetworkRegistrationInfos.size() == s.mNetworkRegistrationInfos.size()
+                    && mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos)
+                    && mNrFrequencyRange == s.mNrFrequencyRange;
+        }
     }
 
     /**
@@ -1005,36 +1013,38 @@
 
     @Override
     public String toString() {
-        return new StringBuilder().append("{mVoiceRegState=").append(mVoiceRegState)
-            .append("(" + rilServiceStateToString(mVoiceRegState) + ")")
-            .append(", mDataRegState=").append(mDataRegState)
-            .append("(" + rilServiceStateToString(mDataRegState) + ")")
-            .append(", mChannelNumber=").append(mChannelNumber)
-            .append(", duplexMode()=").append(getDuplexMode())
-            .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
-            .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
-            .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
-            .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
-            .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
-            .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
-            .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
-            .append(", getRilVoiceRadioTechnology=").append(getRilVoiceRadioTechnology())
-            .append("(" + rilRadioTechnologyToString(getRilVoiceRadioTechnology()) + ")")
-            .append(", getRilDataRadioTechnology=").append(getRilDataRadioTechnology())
-            .append("(" + rilRadioTechnologyToString(getRilDataRadioTechnology()) + ")")
-            .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported")
-            .append(", mNetworkId=").append(mNetworkId)
-            .append(", mSystemId=").append(mSystemId)
-            .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
-            .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
-            .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
-            .append(", isUsingCarrierAggregation=").append(isUsingCarrierAggregation())
-            .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
-            .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
-            .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
-            .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
-            .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
-            .append("}").toString();
+        synchronized (mNetworkRegistrationInfos) {
+            return new StringBuilder().append("{mVoiceRegState=").append(mVoiceRegState)
+                    .append("(" + rilServiceStateToString(mVoiceRegState) + ")")
+                    .append(", mDataRegState=").append(mDataRegState)
+                    .append("(" + rilServiceStateToString(mDataRegState) + ")")
+                    .append(", mChannelNumber=").append(mChannelNumber)
+                    .append(", duplexMode()=").append(getDuplexMode())
+                    .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
+                    .append(", mVoiceOperatorAlphaLong=").append(mVoiceOperatorAlphaLong)
+                    .append(", mVoiceOperatorAlphaShort=").append(mVoiceOperatorAlphaShort)
+                    .append(", mDataOperatorAlphaLong=").append(mDataOperatorAlphaLong)
+                    .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
+                    .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
+                    .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
+                    .append(", getRilVoiceRadioTechnology=").append(getRilVoiceRadioTechnology())
+                    .append("(" + rilRadioTechnologyToString(getRilVoiceRadioTechnology()) + ")")
+                    .append(", getRilDataRadioTechnology=").append(getRilDataRadioTechnology())
+                    .append("(" + rilRadioTechnologyToString(getRilDataRadioTechnology()) + ")")
+                    .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported")
+                    .append(", mNetworkId=").append(mNetworkId)
+                    .append(", mSystemId=").append(mSystemId)
+                    .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
+                    .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
+                    .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
+                    .append(", isUsingCarrierAggregation=").append(isUsingCarrierAggregation())
+                    .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
+                    .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
+                    .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
+                    .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
+                    .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
+                    .append("}").toString();
+        }
     }
 
     private void init() {
@@ -1060,17 +1070,19 @@
         mIsEmergencyOnly = false;
         mLteEarfcnRsrpBoost = 0;
         mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
-        mNetworkRegistrationInfos.clear();
-        addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
-                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
-                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
-                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
-                .build());
-        addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
-                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
-                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
-                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
-                .build());
+        synchronized (mNetworkRegistrationInfos) {
+            mNetworkRegistrationInfos.clear();
+            addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+                    .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+                    .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                    .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+                    .build());
+            addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+                    .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                    .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                    .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+                    .build());
+        }
         mOperatorAlphaLongRaw = null;
         mOperatorAlphaShortRaw = null;
     }
@@ -1913,10 +1925,13 @@
      */
     public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
         ServiceState state = new ServiceState(this);
-        if (state.mNetworkRegistrationInfos != null) {
-            state.mNetworkRegistrationInfos = state.mNetworkRegistrationInfos.stream()
-                    .map(NetworkRegistrationInfo::sanitizeLocationInfo)
-                    .collect(Collectors.toList());
+        synchronized (state.mNetworkRegistrationInfos) {
+            List<NetworkRegistrationInfo> networkRegistrationInfos =
+                    state.mNetworkRegistrationInfos.stream()
+                            .map(NetworkRegistrationInfo::sanitizeLocationInfo)
+                            .collect(Collectors.toList());
+            state.mNetworkRegistrationInfos.clear();
+            state.mNetworkRegistrationInfos.addAll(networkRegistrationInfos);
         }
         if (!removeCoarseLocation) return state;
 
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 64c1830..2552f04 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -209,18 +209,9 @@
                 context.enforcePermission(
                         android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
             } catch (SecurityException phoneStateException) {
-                SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
-                        Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-                int[] activeSubIds = sm.getActiveSubscriptionIdList();
-                for (int activeSubId : activeSubIds) {
-                    // If we don't have the runtime permission, but do have carrier privileges, that
-                    // suffices for reading phone state.
-                    if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
-                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                        return true;
-                    }
-                }
-                return false;
+                // If we don't have the runtime permission, but do have carrier privileges, that
+                // suffices for reading phone state.
+                return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
             }
         }
 
@@ -236,9 +227,9 @@
      *
      * <p>This method behaves in one of the following ways:
      * <ul>
-     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the
-     *       calling package passes a DevicePolicyManager Device Owner / Profile Owner device
-     *       identifier access check,
+     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
+     *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
+     *       access check, or the calling package has carrier privileges.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -258,9 +249,9 @@
      *
      * <p>This method behaves in one of the following ways:
      * <ul>
-     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission or the
-     *       calling package passes a DevicePolicyManager Device Owner / Profile Owner device
-     *       identifier access check,
+     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
+     *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
+     *       access check, or the calling package has carrier privileges.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission
      *       or carrier privileges.
@@ -272,23 +263,8 @@
      */
     public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
             String callingPackage, String message) {
-        int pid = Binder.getCallingPid();
-        int uid = Binder.getCallingUid();
-        // if the device identifier check completes successfully then grant access.
-        if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
-            return true;
-        }
-        // Calling packages with carrier privileges will also have access to device identifiers, but
-        // this may be removed in a future release.
-        if (checkCarrierPrivilegeForSubId(subId)) {
-            return true;
-        }
-        // else the calling package is not authorized to access the device identifiers; call
-        // a central method to report the failure based on the target SDK and if the calling package
-        // has the READ_PHONE_STATE permission or carrier privileges that were previously required
-        // to access the identifiers.
-        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
-                message);
+        return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
+                Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
     }
 
     /**
@@ -298,7 +274,7 @@
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the calling
      *       package passes a DevicePolicyManager Device Owner / Profile Owner device identifier
-     *       access check, or the calling package has carrier privleges.
+     *       access check, or the calling package has carrier privileges.
      *   <li>throw SecurityException: if the caller does not meet any of the requirements and is
      *       targeting Q or is targeting pre-Q and does not have the READ_PHONE_STATE permission.
      *   <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
@@ -309,19 +285,8 @@
      */
     public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
             String callingPackage, String message) {
-        int pid = Binder.getCallingPid();
-        int uid = Binder.getCallingUid();
-        // if the device identifiers can be read then grant access to the subscriber identifiers
-        if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
-            return true;
-        }
-        // If the calling package has carrier privileges then allow access to the subscriber
-        // identifiers.
-        if (checkCarrierPrivilegeForSubId(subId)) {
-            return true;
-        }
-        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
-                message);
+        return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
+                Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
     }
 
     /**
@@ -331,8 +296,10 @@
      * package passes a DevicePolicyManager Device Owner / Profile Owner device identifier access
      * check.
      */
-    private static boolean checkReadDeviceIdentifiers(Context context, int pid, int uid,
-            String callingPackage) {
+    @VisibleForTesting
+    public static boolean checkReadDeviceIdentifiers(Context context,
+            Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+            String callingPackage, String message) {
         // Allow system and root access to the device identifiers.
         final int appId = UserHandle.getAppId(uid);
         if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
@@ -343,31 +310,36 @@
                 uid) == PackageManager.PERMISSION_GRANTED) {
             return true;
         }
-        // if the calling package is null then return now as there's no way to perform the
-        // DevicePolicyManager device / profile owner and AppOp checks
-        if (callingPackage == null) {
-            return false;
-        }
-        // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
-        long token = Binder.clearCallingIdentity();
-        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
-                Context.APP_OPS_SERVICE);
-        try {
-            if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
-                    callingPackage) == AppOpsManager.MODE_ALLOWED) {
-                return true;
-            }
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        // Allow access to a device / profile owner app.
-        DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
-                callingPackage, pid, uid)) {
+        // If the calling package has carrier privileges for any subscription then allow access.
+        if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) {
             return true;
         }
-        return false;
+        // if the calling package is not null then perform the DevicePolicyManager device /
+        // profile owner and Appop checks.
+        if (callingPackage != null) {
+            // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
+            long token = Binder.clearCallingIdentity();
+            AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
+                    Context.APP_OPS_SERVICE);
+            try {
+                if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
+                        callingPackage) == AppOpsManager.MODE_ALLOWED) {
+                    return true;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            // Allow access to a device / profile owner app.
+            DevicePolicyManager devicePolicyManager =
+                    (DevicePolicyManager) context.getSystemService(
+                            Context.DEVICE_POLICY_SERVICE);
+            if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
+                    callingPackage, pid, uid)) {
+                return true;
+            }
+        }
+        return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
+            message);
     }
 
     /**
@@ -403,10 +375,12 @@
         try {
             callingPackageInfo = context.getPackageManager().getApplicationInfoAsUser(
                     callingPackage, 0, UserHandle.getUserId(uid));
-            if (callingPackageInfo.isSystemApp()) {
-                isPreinstalled = true;
-                if (callingPackageInfo.isPrivilegedApp()) {
-                    isPrivApp = true;
+            if (callingPackageInfo != null) {
+                if (callingPackageInfo.isSystemApp()) {
+                    isPreinstalled = true;
+                    if (callingPackageInfo.isPrivilegedApp()) {
+                        isPrivApp = true;
+                    }
                 }
             }
         } catch (PackageManager.NameNotFoundException e) {
@@ -651,6 +625,26 @@
         }
     }
 
+    /**
+     * Returns whether the provided uid has carrier privileges for any active subscription ID.
+     */
+    private static boolean checkCarrierPrivilegeForAnySubId(Context context,
+            Supplier<ITelephony> telephonySupplier, int uid) {
+        SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        int[] activeSubIds = sm.getActiveSubscriptionIdList();
+        if (activeSubIds != null) {
+            for (int activeSubId : activeSubIds) {
+                if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+                        == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
     private static int getCarrierPrivilegeStatus(
             Supplier<ITelephony> telephonySupplier, int subId, int uid) {
         ITelephony telephony = telephonySupplier.get();
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index 8ff2de9..6e69b34 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -111,13 +111,12 @@
 
     @Test
     public void testNetworkAttributes() throws Exception {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
         final String l2Key = "fakeKey";
 
         mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         verify(mMockService, times(1)).storeNetworkAttributes(eq(l2Key),
                 mNapCaptor.capture(), any());
         assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
@@ -135,7 +134,7 @@
 
     @Test
     public void testPrivateData() throws RemoteException {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
         final Blob b = new Blob();
         b.data = TEST_BLOB_DATA;
         final String l2Key = "fakeKey";
@@ -162,7 +161,7 @@
     @Test
     public void testFindL2Key()
             throws UnknownHostException, RemoteException, Exception {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
         final String l2Key = "fakeKey";
 
         mStore.findL2Key(TEST_NETWORK_ATTRIBUTES,
@@ -177,7 +176,7 @@
 
     @Test
     public void testIsSameNetwork() throws UnknownHostException, RemoteException {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
         final String l2Key1 = "fakeKey1";
         final String l2Key2 = "fakeKey2";
 
@@ -193,7 +192,7 @@
 
     @Test
     public void testEnqueuedIpMsRequests() throws Exception {
-        startIpMemoryStore(false);
+        startIpMemoryStore(false /* supplyService */);
 
         final Blob b = new Blob();
         b.data = TEST_BLOB_DATA;
@@ -201,9 +200,8 @@
 
         // enqueue multiple ipms requests
         mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         mStore.retrieveNetworkAttributes(l2Key,
                 (status, key, attr) -> {
                     assertTrue("Retrieve network attributes not successful : "
@@ -212,9 +210,8 @@
                     assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
                 });
         mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
                 (status, key, name, data) -> {
                     assertTrue("Retrieve blob status not successful : " + status.resultCode,
@@ -240,7 +237,7 @@
 
     @Test
     public void testEnqueuedIpMsRequestsWithException() throws Exception {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
         doThrow(RemoteException.class).when(mMockService).retrieveNetworkAttributes(any(), any());
 
         final Blob b = new Blob();
@@ -249,9 +246,8 @@
 
         // enqueue multiple ipms requests
         mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         mStore.retrieveNetworkAttributes(l2Key,
                 (status, key, attr) -> {
                     assertTrue("Retrieve network attributes not successful : "
@@ -260,9 +256,8 @@
                     assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
                 });
         mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
                 (status, key, name, data) -> {
                     assertTrue("Retrieve blob status not successful : " + status.resultCode,
@@ -286,7 +281,7 @@
 
     @Test
     public void testEnqueuedIpMsRequestsCallbackFunctionWithException() throws Exception {
-        startIpMemoryStore(true);
+        startIpMemoryStore(true /* supplyService */);
 
         final Blob b = new Blob();
         b.data = TEST_BLOB_DATA;
@@ -294,9 +289,8 @@
 
         // enqueue multiple ipms requests
         mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
-                status -> {
-                    assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
-                });
+                status -> assertTrue("Store not successful : " + status.resultCode,
+                        status.isSuccess()));
         mStore.retrieveNetworkAttributes(l2Key,
                 (status, key, attr) -> {
                     throw new RuntimeException("retrieveNetworkAttributes test");
@@ -320,6 +314,7 @@
 
         inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(),
                 any());
+        inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any());
         inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
                 eq(b), any());
         inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h
index c1fcf5c..27ffcdf 100644
--- a/tools/aapt/SdkConstants.h
+++ b/tools/aapt/SdkConstants.h
@@ -44,6 +44,7 @@
     SDK_O = 26,
     SDK_O_MR1 = 27,
     SDK_P = 28,
+    SDK_Q = 29,
 };
 
 #endif // H_AAPT_SDK_CONSTANTS
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 9fa29f2..580daab 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -54,6 +54,7 @@
   SDK_O = 26,
   SDK_O_MR1 = 27,
   SDK_P = 28,
+  SDK_Q = 29,
 };
 
 ApiVersion FindAttributeSdkLevel(const ResourceId& id);
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index f191f6c..6683e2a 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -490,11 +490,6 @@
 def flag_sequence(territory_code):
     return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
 
-UNSUPPORTED_FLAGS = frozenset({
-    flag_sequence('BL'), flag_sequence('BQ'), flag_sequence('MQ'),
-    flag_sequence('RE'), flag_sequence('TF'),
-})
-
 EQUIVALENT_FLAGS = {
     flag_sequence('BV'): flag_sequence('NO'),
     flag_sequence('CP'): flag_sequence('FR'),
@@ -600,9 +595,6 @@
     for first, second in SAME_FLAG_MAPPINGS:
         equivalent_emoji[first] = second
 
-    # Remove unsupported flags
-    all_sequences.difference_update(UNSUPPORTED_FLAGS)
-
     # Add all tag characters used in flags
     sequence_pieces.update(range(0xE0030, 0xE0039 + 1))
     sequence_pieces.update(range(0xE0061, 0xE007A + 1))