Merge "Prevent reflection - ScaleGestureDetector#mMinSpan"
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
new file mode 100644
index 0000000..8a676e9
--- /dev/null
+++ b/api/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsCurrentApiSignatureTestCases"
+    }
+  ]
+}
diff --git a/api/current.txt b/api/current.txt
index 520bda1..cb719c3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14191,13 +14191,16 @@
     field public static final int YV12 = 842094169; // 0x32315659
   }
 
-  public final class Insets {
+  public final class Insets implements android.os.Parcelable {
     method @NonNull public static android.graphics.Insets add(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
+    method public int describeContents();
     method @NonNull public static android.graphics.Insets max(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
     method @NonNull public static android.graphics.Insets min(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
     method @NonNull public static android.graphics.Insets of(int, int, int, int);
     method @NonNull public static android.graphics.Insets of(@Nullable android.graphics.Rect);
     method @NonNull public static android.graphics.Insets subtract(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.Insets> CREATOR;
     field public static final android.graphics.Insets NONE;
     field public final int bottom;
     field public final int left;
@@ -16489,6 +16492,7 @@
     field public static final int BIOMETRIC_ERROR_LOCKOUT = 7; // 0x7
     field public static final int BIOMETRIC_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
     field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
+    field public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14; // 0xe
     field public static final int BIOMETRIC_ERROR_NO_SPACE = 4; // 0x4
     field public static final int BIOMETRIC_ERROR_TIMEOUT = 3; // 0x3
     field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
@@ -16511,8 +16515,8 @@
   public static class BiometricPrompt.Builder {
     ctor public BiometricPrompt.Builder(android.content.Context);
     method public android.hardware.biometrics.BiometricPrompt build();
+    method public android.hardware.biometrics.BiometricPrompt.Builder setAllowDeviceCredential(boolean);
     method public android.hardware.biometrics.BiometricPrompt.Builder setDescription(@NonNull CharSequence);
-    method public android.hardware.biometrics.BiometricPrompt.Builder setEnableFallback(boolean);
     method public android.hardware.biometrics.BiometricPrompt.Builder setNegativeButton(@NonNull CharSequence, @NonNull java.util.concurrent.Executor, @NonNull android.content.DialogInterface.OnClickListener);
     method public android.hardware.biometrics.BiometricPrompt.Builder setRequireConfirmation(boolean);
     method public android.hardware.biometrics.BiometricPrompt.Builder setSubtitle(@NonNull CharSequence);
@@ -24535,7 +24539,9 @@
   }
 
   public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+    ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int);
     method public boolean covers(@NonNull android.media.MediaFormat);
+    method public boolean covers(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint);
     field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
     field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
     field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
@@ -24570,8 +24576,8 @@
     field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
     field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
     field public final int frameRate;
-    field public final int height;
-    field public final int width;
+    field public final long macroBlockRate;
+    field public final int macroBlocks;
   }
 
   public final class MediaCodecList {
@@ -38340,11 +38346,7 @@
     method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
     method @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
-    method @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
     method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
-    method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
-    method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
-    method public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
     field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
     field public static final String ACTION_REVIEW = "android.provider.action.REVIEW";
@@ -38615,14 +38617,14 @@
   public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
     field @Deprecated public static final String DATA = "_data";
     field public static final String DATE_ADDED = "date_added";
-    field public static final String DATE_EXPIRES = "date_expires";
     field public static final String DATE_MODIFIED = "date_modified";
     field public static final String DISPLAY_NAME = "_display_name";
-    field public static final String HASH = "_hash";
+    field public static final String DOCUMENT_ID = "document_id";
     field public static final String HEIGHT = "height";
+    field public static final String INSTANCE_ID = "instance_id";
     field public static final String IS_PENDING = "is_pending";
-    field public static final String IS_TRASHED = "is_trashed";
     field public static final String MIME_TYPE = "mime_type";
+    field public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
     field public static final String OWNER_PACKAGE_NAME = "owner_package_name";
     field public static final String PRIMARY_DIRECTORY = "primary_directory";
     field public static final String SECONDARY_DIRECTORY = "secondary_directory";
@@ -49550,6 +49552,7 @@
     ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
     method public abstract android.view.LayoutInflater cloneInContext(android.content.Context);
     method public final android.view.View createView(String, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
+    method @Nullable public final android.view.View createView(@NonNull android.content.Context, @NonNull String, @Nullable String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException, android.view.InflateException;
     method public static android.view.LayoutInflater from(android.content.Context);
     method public android.content.Context getContext();
     method public final android.view.LayoutInflater.Factory getFactory();
@@ -49561,6 +49564,7 @@
     method public android.view.View inflate(org.xmlpull.v1.XmlPullParser, @Nullable android.view.ViewGroup, boolean);
     method protected android.view.View onCreateView(String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
     method protected android.view.View onCreateView(android.view.View, String, android.util.AttributeSet) throws java.lang.ClassNotFoundException;
+    method @Nullable public android.view.View onCreateView(@NonNull android.content.Context, @Nullable android.view.View, @NonNull String, @Nullable android.util.AttributeSet) throws java.lang.ClassNotFoundException;
     method public void setFactory(android.view.LayoutInflater.Factory);
     method public void setFactory2(android.view.LayoutInflater.Factory2);
     method public void setFilter(android.view.LayoutInflater.Filter);
@@ -54850,6 +54854,7 @@
     method public void deferNotifyDataSetChanged();
     method public void fling(int);
     method public android.widget.AbsListView.LayoutParams generateLayoutParams(android.util.AttributeSet);
+    method @ColorInt public int getBottomEdgeEffectColor();
     method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getCacheColorHint();
     method public int getCheckedItemCount();
     method public long[] getCheckedItemIds();
@@ -54864,6 +54869,7 @@
     method @android.view.ViewDebug.ExportedProperty public android.view.View getSelectedView();
     method public android.graphics.drawable.Drawable getSelector();
     method public CharSequence getTextFilter();
+    method @ColorInt public int getTopEdgeEffectColor();
     method public int getTranscriptMode();
     method protected void handleDataChanged();
     method public boolean hasTextFilter();
@@ -54891,9 +54897,11 @@
     method public void reclaimViews(java.util.List<android.view.View>);
     method public void scrollListBy(int);
     method public void setAdapter(android.widget.ListAdapter);
+    method public void setBottomEdgeEffectColor(@ColorInt int);
     method public void setCacheColorHint(@ColorInt int);
     method public void setChoiceMode(int);
     method public void setDrawSelectorOnTop(boolean);
+    method public void setEdgeEffectColor(@ColorInt int);
     method public void setFastScrollAlwaysVisible(boolean);
     method public void setFastScrollEnabled(boolean);
     method public void setFastScrollStyle(int);
@@ -54912,6 +54920,7 @@
     method public void setSmoothScrollbarEnabled(boolean);
     method public void setStackFromBottom(boolean);
     method public void setTextFilterEnabled(boolean);
+    method public void setTopEdgeEffectColor(@ColorInt int);
     method public void setTranscriptMode(int);
     method public void setVelocityScale(float);
     method public void smoothScrollBy(int, int);
@@ -55544,6 +55553,7 @@
     ctor public EdgeEffect(android.content.Context);
     method public boolean draw(android.graphics.Canvas);
     method public void finish();
+    method @Nullable public android.graphics.BlendMode getBlendMode();
     method @ColorInt public int getColor();
     method public int getMaxHeight();
     method public boolean isFinished();
@@ -55551,8 +55561,10 @@
     method public void onPull(float);
     method public void onPull(float, float);
     method public void onRelease();
+    method public void setBlendMode(@Nullable android.graphics.BlendMode);
     method public void setColor(@ColorInt int);
     method public void setSize(int, int);
+    field public static final android.graphics.BlendMode DEFAULT_BLEND_MODE;
   }
 
   public class EditText extends android.widget.TextView {
@@ -56288,6 +56300,7 @@
     method public android.view.View getContentView();
     method public float getElevation();
     method @Nullable public android.transition.Transition getEnterTransition();
+    method @Nullable public android.graphics.Rect getEpicenterBounds();
     method @Nullable public android.transition.Transition getExitTransition();
     method public int getHeight();
     method public int getInputMethodMode();
@@ -56300,30 +56313,37 @@
     method public int getWindowLayoutType();
     method public boolean isAboveAnchor();
     method public boolean isAttachedInDecor();
+    method public boolean isClipToScreenEnabled();
     method public boolean isClippingEnabled();
     method public boolean isFocusable();
+    method public boolean isLayoutInScreenEnabled();
     method public boolean isOutsideTouchable();
     method public boolean isShowing();
     method public boolean isSplitTouchEnabled();
+    method public boolean isTouchModal();
     method public boolean isTouchable();
     method public void setAnimationStyle(int);
     method public void setAttachedInDecor(boolean);
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public void setClipToScreenEnabled(boolean);
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
     method public void setElevation(float);
     method public void setEnterTransition(@Nullable android.transition.Transition);
+    method public void setEpicenterBounds(@Nullable android.graphics.Rect);
     method public void setExitTransition(@Nullable android.transition.Transition);
     method public void setFocusable(boolean);
     method public void setHeight(int);
     method public void setIgnoreCheekPress();
     method public void setInputMethodMode(int);
+    method public void setLayoutInScreenEnabled(boolean);
     method public void setOnDismissListener(android.widget.PopupWindow.OnDismissListener);
     method public void setOutsideTouchable(boolean);
     method public void setOverlapAnchor(boolean);
     method public void setSoftInputMode(int);
     method public void setSplitTouchEnabled(boolean);
     method public void setTouchInterceptor(android.view.View.OnTouchListener);
+    method public void setTouchModal(boolean);
     method public void setTouchable(boolean);
     method public void setWidth(int);
     method @Deprecated public void setWindowLayoutMode(int, int);
diff --git a/api/removed.txt b/api/removed.txt
index 262ffec..f5bd434 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -507,6 +507,19 @@
     field @Deprecated public static final String TIMESTAMP = "timestamp";
   }
 
+  public final class MediaStore {
+    method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
+    method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
+    method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
+    method @Deprecated public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
+  }
+
+  public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
+    field @Deprecated public static final String DATE_EXPIRES = "date_expires";
+    field @Deprecated public static final String HASH = "_hash";
+    field @Deprecated public static final String IS_TRASHED = "is_trashed";
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field @Deprecated public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index b7fc339..3a50239 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -201,7 +201,6 @@
   }
 
   public static final class R.array {
-    field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
     field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
   }
 
@@ -237,6 +236,10 @@
   }
 
   public static final class R.string {
+    field public static final int config_defaultAssistant = 17039393; // 0x1040021
+    field public static final int config_defaultBrowser = 17039394; // 0x1040022
+    field public static final int config_defaultDialer = 17039395; // 0x1040023
+    field public static final int config_defaultSms = 17039396; // 0x1040024
     field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f
     field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020
     field public static final int config_helpIntentExtraKey = 17039389; // 0x104001d
@@ -5739,10 +5742,6 @@
     field public static final String SERVICE_ENABLED = "service_enabled";
   }
 
-  public static interface DeviceConfig.ContentCapture {
-    field public static final String NAMESPACE = "content_capture";
-  }
-
   public static interface DeviceConfig.DexBoot {
     field public static final String NAMESPACE = "dex_boot";
     field public static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
@@ -5777,11 +5776,6 @@
     field public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
   }
 
-  public static interface DeviceConfig.Runtime {
-    field public static final String NAMESPACE = "runtime";
-    field public static final String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
-  }
-
   public static interface DeviceConfig.RuntimeNative {
     field public static final String NAMESPACE = "runtime_native";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 2c8d08c..9e266d8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17,8 +17,9 @@
     field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
   }
 
-  public static final class R.array {
-    field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
+  public static final class R.string {
+    field public static final int config_defaultAssistant = 17039393; // 0x1040021
+    field public static final int config_defaultDialer = 17039395; // 0x1040023
   }
 
 }
@@ -1784,8 +1785,10 @@
   }
 
   public final class DeviceConfig {
+    method @RequiresPermission("android.permission.READ_DEVICE_CONFIG") public static String getProperty(String, String);
     method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static void resetToDefaults(int, @Nullable String);
     method @RequiresPermission("android.permission.WRITE_DEVICE_CONFIG") public static boolean setProperty(String, String, String, boolean);
+    field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
   }
 
   public static interface DeviceConfig.Privacy {
@@ -1853,6 +1856,7 @@
     field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
     field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
     field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
+    field public static final String NOTIFICATION_BADGING = "notification_badging";
     field public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
     field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
     field public static final String USER_SETUP_COMPLETE = "user_setup_complete";
@@ -2717,6 +2721,7 @@
   public final class ContentCaptureManager {
     method public boolean isContentCaptureFeatureEnabled();
     method public void setContentCaptureFeatureEnabled(boolean);
+    field public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled";
   }
 
   public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
diff --git a/cmds/idmap2/static-checks.sh b/cmds/idmap2/static-checks.sh
index 5740710..41d3c69 100755
--- a/cmds/idmap2/static-checks.sh
+++ b/cmds/idmap2/static-checks.sh
@@ -59,7 +59,7 @@
 
 function _bpfmt()
 {
-    local output="$(bpfmt -s -d $bp_files)"
+    local output="$(bpfmt -d $bp_files)"
     if [[ "$output" ]]; then
         echo "$output"
         return 1
@@ -72,6 +72,7 @@
     local cpplint="${ANDROID_BUILD_TOP}/tools/repohooks/tools/cpplint.py"
     local output="$($cpplint --quiet $cpp_files 2>&1 >/dev/null | grep -v \
         -e 'Found C system header after C++ system header.' \
+        -e 'Unknown NOLINT error category: cert-dcl50-cpp' \
         -e 'Unknown NOLINT error category: misc-non-private-member-variables-in-classes' \
         -e 'Unknown NOLINT error category: performance-unnecessary-copy-initialization' \
     )"
@@ -116,7 +117,7 @@
     exit $errors
 elif [[ $opt_mode == "fix" ]]; then
     clang-format -style=file -i $cpp_files
-    bpfmt -s -w $bp_files
+    bpfmt -w $bp_files
     exit 0
 elif [[ $opt_mode == "help" ]]; then
     echo "Run static analysis tools such as clang-format and cpplint on the idmap2"
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index 40da583..3dc1093 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -94,8 +94,10 @@
 
     data: ["testdata/**/*"],
 
-    static_libs: ["libgmock"],
-
+    static_libs: [
+        "libgmock",
+        "libplatformprotos",
+    ],
     shared_libs: [
         "libbase",
         "libbinder",
diff --git a/cmds/incidentd/tests/Reporter_test.cpp b/cmds/incidentd/tests/Reporter_test.cpp
index f54f738..b5e41d7 100644
--- a/cmds/incidentd/tests/Reporter_test.cpp
+++ b/cmds/incidentd/tests/Reporter_test.cpp
@@ -35,6 +35,16 @@
 using ::testing::StrEq;
 using ::testing::Test;
 
+namespace {
+void getHeaderData(const IncidentHeaderProto& headerProto, vector<uint8_t>* out) {
+    out->clear();
+    auto serialized = headerProto.SerializeAsString();
+    if (serialized.empty()) return;
+    out->resize(serialized.length());
+    std::copy(serialized.begin(), serialized.end(), out->begin());
+}
+}
+
 class TestListener : public IIncidentReportStatusListener {
 public:
     int startInvoked;
@@ -143,7 +153,10 @@
     args2.addSection(2);
     IncidentHeaderProto header;
     header.set_alert_id(12);
-    args2.addHeader(header);
+
+    vector<uint8_t> out;
+    getHeaderData(header, &out);
+    args2.addHeader(out);
     sp<ReportRequest> r1 = new ReportRequest(args1, l, tf.fd);
     sp<ReportRequest> r2 = new ReportRequest(args2, l, tf.fd);
 
@@ -169,8 +182,12 @@
     IncidentHeaderProto header1, header2;
     header1.set_alert_id(12);
     header2.set_reason("abcd");
-    args.addHeader(header1);
-    args.addHeader(header2);
+
+    vector<uint8_t> out;
+    getHeaderData(header1, &out);
+    args.addHeader(out);
+    getHeaderData(header2, &out);
+    args.addHeader(out);
     sp<ReportRequest> r = new ReportRequest(args, l, -1);
     reporter->batch.add(r);
 
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 9b684a0..24454ed 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -82,6 +82,16 @@
     virtual IBinder* onAsBinder() override { return nullptr; };
 };
 
+namespace {
+void getHeaderData(const IncidentHeaderProto& headerProto, vector<uint8_t>* out) {
+    out->clear();
+    auto serialized = headerProto.SerializeAsString();
+    if (serialized.empty()) return;
+    out->resize(serialized.length());
+    std::copy(serialized.begin(), serialized.end(), out->begin());
+}
+}
+
 TEST_F(SectionTest, HeaderSection) {
     HeaderSection hs;
 
@@ -94,9 +104,15 @@
     head1.set_reason("axe");
     head2.set_reason("pup");
 
-    args1.addHeader(head1);
-    args1.addHeader(head2);
-    args2.addHeader(head2);
+    vector<uint8_t> out;
+    getHeaderData(head1, &out);
+    args1.addHeader(out);
+
+    getHeaderData(head2, &out);
+    args1.addHeader(out);
+
+    getHeaderData(head2, &out);
+    args2.addHeader(out);
 
     requests.add(new ReportRequest(args1, new SimpleListener(), -1));
     requests.add(new ReportRequest(args2, new SimpleListener(), tf.fd));
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 250f5bf..dd18bd4 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -526,9 +526,10 @@
         proto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_ID, (long long)pair.first.GetId());
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_UID, pair.first.GetUid());
 
-        vector<const MetricProducer*> acrtiveMetrics;
-        pair.second->getActiveMetrics(acrtiveMetrics);
-        for (const MetricProducer* metric : acrtiveMetrics) {
+        vector<MetricProducer*> activeMetrics;
+        pair.second->prepForShutDown(currentTimeNs);
+        pair.second->getActiveMetrics(activeMetrics);
+        for (MetricProducer* metric : activeMetrics) {
             if (metric->isActive()) {
                 uint64_t metricToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
                                                    FIELD_ID_ACTIVE_METRIC);
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 77d9a2f..caf1a71 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -195,6 +195,7 @@
     FRIEND_TEST(StatsLogProcessorTest, TestRateLimitBroadcast);
     FRIEND_TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge);
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
 
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1);
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2);
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index ad5eae3..6b46b8b 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -23,7 +23,6 @@
 
 #include "external/Perfetto.h"
 #include "external/Perfprofd.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
 #include "subscriber/IncidentdReporter.h"
 #include "subscriber/SubscriberReporter.h"
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4f17d69..c75ca8b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -41,12 +41,13 @@
 import "frameworks/base/core/proto/android/service/usb.proto";
 import "frameworks/base/core/proto/android/stats/enums.proto";
 import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
+import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
+import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
 import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
-import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
-import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
+import "frameworks/base/core/proto/android/wifi/enums.proto";
 
 /**
  * The master atom class. This message defines all of the available
@@ -214,7 +215,7 @@
         SpeechDspStatReported speech_dsp_stat_reported = 145;
         UsbContaminantReported usb_contaminant_reported = 146;
         WatchdogRollbackOccurred watchdog_rollback_occurred = 147;
-        BiometricHalDeathReported biometric_hal_death_reported = 148;
+        BiometricSystemHealthIssueDetected biometric_system_health_issue_detected = 148;
         BubbleUIChanged bubble_ui_changed = 149;
         ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
         BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
@@ -994,6 +995,9 @@
         ON = 1;
     }
     optional State state = 2;
+
+    // WifiLock type, from frameworks/base/core/proto/android/wifi/enums.proto.
+    optional android.net.wifi.WifiModeEnum mode = 3;
 }
 
 /**
@@ -3046,13 +3050,15 @@
 }
 
 /**
- * Logs when a biometric HAL has crashed.
+ * Logs when a system health issue is detected.
  * Logged from:
  *   frameworks/base/services/core/java/com/android/server/biometrics
  */
-message BiometricHalDeathReported {
+message BiometricSystemHealthIssueDetected {
     // Biometric modality.
     optional android.hardware.biometrics.ModalityEnum modality = 1;
+    // Type of issue detected.
+    optional android.hardware.biometrics.IssueEnum issue = 2;
 }
 
 message Notification {
diff --git a/cmds/statsd/src/external/PullDataReceiver.h b/cmds/statsd/src/external/PullDataReceiver.h
index b071682..d2193f4 100644
--- a/cmds/statsd/src/external/PullDataReceiver.h
+++ b/cmds/statsd/src/external/PullDataReceiver.h
@@ -32,9 +32,10 @@
    * @param data The pulled data.
    * @param pullSuccess Whether the pull succeeded. If the pull does not succeed, the data for the
    * bucket should be invalidated.
+   * @param originalPullTimeNs This is when all the pulls have been initiated (elapsed time).
    */
   virtual void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data, 
-                            bool pullSuccess) = 0;
+                            bool pullSuccess, int64_t originalPullTimeNs) = 0;
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9b603d6..ecdcd21 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -174,9 +174,12 @@
         // Size of specific categories of files. Eg. Music.
         {android::util::CATEGORY_SIZE,
          {.puller = new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
-        // Number of fingerprints registered to each user.
+        // Number of fingerprints enrolled for each user.
         {android::util::NUM_FINGERPRINTS_ENROLLED,
          {.puller = new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS_ENROLLED)}},
+        // Number of faces enrolled for each user.
+        {android::util::NUM_FACES_ENROLLED,
+         {.puller = new StatsCompanionServicePuller(android::util::NUM_FACES_ENROLLED)}},
         // ProcStats.
         {android::util::PROC_STATS,
          {.puller = new StatsCompanionServicePuller(android::util::PROC_STATS)}},
@@ -381,7 +384,7 @@
         for (const auto& receiverInfo : pullInfo.second) {
             sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote();
             if (receiverPtr != nullptr) {
-                receiverPtr->onDataPulled(data, pullSuccess);
+                receiverPtr->onDataPulled(data, pullSuccess, elapsedTimeNs);
                 // We may have just come out of a coma, compute next pull time.
                 int numBucketsAhead =
                         (elapsedTimeNs - receiverInfo->nextPullTimeNs) / receiverInfo->intervalNs;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 37d5ba0..c4034ff 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -423,41 +423,50 @@
     mPulledAtomStats[atomId].emptyData++;
 }
 
-void StatsdStats::noteHardDimensionLimitReached(int metricId) {
+void StatsdStats::noteHardDimensionLimitReached(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).hardDimensionLimitReached++;
 }
 
-void StatsdStats::noteLateLogEventSkipped(int metricId) {
+void StatsdStats::noteLateLogEventSkipped(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).lateLogEventSkipped++;
 }
 
-void StatsdStats::noteSkippedForwardBuckets(int metricId) {
+void StatsdStats::noteSkippedForwardBuckets(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).skippedForwardBuckets++;
 }
 
-void StatsdStats::noteBadValueType(int metricId) {
+void StatsdStats::noteBadValueType(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).badValueType++;
 }
 
-void StatsdStats::noteBucketDropped(int metricId) {
+void StatsdStats::noteBucketDropped(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).bucketDropped++;
 }
 
-void StatsdStats::noteConditionChangeInNextBucket(int metricId) {
+void StatsdStats::noteConditionChangeInNextBucket(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).conditionChangeInNextBucket++;
 }
 
-void StatsdStats::noteInvalidatedBucket(int metricId) {
+void StatsdStats::noteInvalidatedBucket(int64_t metricId) {
     lock_guard<std::mutex> lock(mLock);
     getAtomMetricStats(metricId).invalidatedBucket++;
 }
 
+void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs) {
+    lock_guard<std::mutex> lock(mLock);
+    AtomMetricStats& pullStats = getAtomMetricStats(metricId);
+    pullStats.maxBucketBoundaryDelayNs =
+            std::max(pullStats.maxBucketBoundaryDelayNs, timeDelayNs);
+    pullStats.minBucketBoundaryDelayNs =
+            std::min(pullStats.minBucketBoundaryDelayNs, timeDelayNs);
+}
+
 StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int metricId) {
     auto atomMetricStatsIter = mAtomMetricStats.find(metricId);
     if (atomMetricStatsIter != mAtomMetricStats.end()) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 20ea7e5..2999b64 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -342,37 +342,43 @@
     /**
      * Hard limit was reached in the cardinality of an atom
      */
-    void noteHardDimensionLimitReached(int atomId);
+    void noteHardDimensionLimitReached(int64_t metricId);
 
     /**
      * A log event was too late, arrived in the wrong bucket and was skipped
      */
-    void noteLateLogEventSkipped(int atomId);
+    void noteLateLogEventSkipped(int64_t metricId);
 
     /**
      * Buckets were skipped as time elapsed without any data for them
      */
-    void noteSkippedForwardBuckets(int atomId);
+    void noteSkippedForwardBuckets(int64_t metricId);
 
     /**
      * An unsupported value type was received
      */
-    void noteBadValueType(int atomId);
+    void noteBadValueType(int64_t metricId);
 
     /**
      * Buckets were dropped due to reclaim memory.
      */
-    void noteBucketDropped(int metricId);
+    void noteBucketDropped(int64_t metricId);
 
     /**
      * A condition change was too late, arrived in the wrong bucket and was skipped
      */
-    void noteConditionChangeInNextBucket(int atomId);
+    void noteConditionChangeInNextBucket(int64_t metricId);
 
     /**
      * A bucket has been tagged as invalid.
      */
-    void noteInvalidatedBucket(int metricId);
+    void noteInvalidatedBucket(int64_t metricId);
+
+    /**
+     * For pulls at bucket boundaries, it represents the misalignment between the real timestamp and
+     * the end of the bucket.
+     */
+    void noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs);
 
     /**
      * Reset the historical stats. Including all stats in icebox, and the tracked stats about
@@ -420,6 +426,8 @@
         long conditionChangeInNextBucket = 0;
         long invalidatedBucket = 0;
         long bucketDropped = 0;
+        int64_t minBucketBoundaryDelayNs = 0;
+        int64_t maxBucketBoundaryDelayNs = 0;
     } AtomMetricStats;
 
 private:
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2609937..d56a355 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -407,7 +407,7 @@
 }
 
 void GaugeMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
-                                       bool pullSuccess) {
+                                       bool pullSuccess, int64_t originalPullTimeNs) {
     std::lock_guard<std::mutex> lock(mMutex);
     if (!pullSuccess || allData.size() == 0) {
         return;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index d480941..64a1833 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -68,7 +68,7 @@
 
     // Handles when the pulled data arrives.
     void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
-                      bool pullSuccess) override;
+                      bool pullSuccess, int64_t originalPullTimeNs) override;
 
     // GaugeMetric needs to immediately trigger another pull when we create the partial bucket.
     void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index b362e37..495138e 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -107,6 +107,10 @@
     if (it == mEventActivationMap.end()) {
         return;
     }
+    if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT) {
+        it->second.state = ActivationState::kActiveOnBoot;
+        return;
+    }
     it->second.activation_ns = elapsedTimestampNs;
     it->second.state = ActivationState::kActive;
     mIsActive = true;
@@ -116,12 +120,19 @@
     if (mEventActivationMap.size() == 0) {
         return;
     }
-    auto& activation = mEventActivationMap.begin()->second;
-    activation.activation_ns = currentTimeNs + remainingTtlNs - activation.ttl_ns;
-    activation.state = kActive;
-    mIsActive = true;
-    VLOG("setting new activation time to %lld, %lld, %lld", (long long)activation.activation_ns,
-         (long long)currentTimeNs, (long long)remainingTtlNs);
+    for (auto& pair : mEventActivationMap) {
+        auto& activation = pair.second;
+        if (activation.ttl_ns >= remainingTtlNs) {
+            activation.activation_ns = currentTimeNs + remainingTtlNs - activation.ttl_ns;
+            activation.state = kActive;
+            mIsActive = true;
+            VLOG("setting new activation time to %lld, %lld, %lld",
+                 (long long)activation.activation_ns, (long long)currentTimeNs,
+                 (long long)remainingTtlNs);
+            return;
+        }
+    }
+    ALOGE("Required ttl is longer than all possible activations.");
 }
 
 int64_t MetricProducer::getRemainingTtlNsLocked(int64_t currentTimeNs) const {
@@ -135,6 +146,19 @@
     return maxTtl;
 }
 
+void MetricProducer::prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs) {
+    if (mActivationType != MetricActivation::ACTIVATE_ON_BOOT) {
+        return;
+    }
+    for (auto& activation : mEventActivationMap) {
+        if (activation.second.state == kActiveOnBoot) {
+            activation.second.state = kActive;
+            activation.second.activation_ns = currentTimeNs;
+            mIsActive = true;
+        }
+    }
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index ca37bbb..849cb76 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -37,12 +37,13 @@
 // 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
-// with kNotActive state, turn to kActive when the activation event arrives, become kNotActive
-// when it reaches the duration limit (timebomb). If the activation event arrives again before
-// or after it expires, the event producer will be re-activated and ttl will be reset.
+// with kNotActive state, turn to kActive or kActiveOnBoot when the activation event arrives, become
+// kNotActive when it reaches the duration limit (timebomb). If the activation event arrives again
+// before or after it expires, the event producer will be re-activated and ttl will be reset.
 enum ActivationState {
     kNotActive = 0,
     kActive = 1,
+    kActiveOnBoot = 2,
 };
 
 // A MetricProducer is responsible for compute one single metrics, creating stats log report, and
@@ -218,8 +219,17 @@
         return isActiveLocked();
     }
 
+    void prepActiveForBootIfNecessary(int64_t currentTimeNs) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        prepActiveForBootIfNecessaryLocked(currentTimeNs);
+    }
+
     void addActivation(int activationTrackerIndex, int64_t ttl_seconds);
 
+    inline void setActivationType(const MetricActivation::ActivationType& activationType) {
+        mActivationType = activationType;
+    }
+
     void flushIfExpire(int64_t elapsedTimestampNs);
 
 protected:
@@ -243,6 +253,8 @@
         return mIsActive;
     }
 
+    void prepActiveForBootIfNecessaryLocked(int64_t currentTimeNs);
+
     int64_t getRemainingTtlNsLocked(int64_t currentTimeNs) const;
 
     void setActiveLocked(int64_t currentTimeNs, int64_t remainingTtlNs);
@@ -367,9 +379,12 @@
 
     bool mIsActive;
 
+    MetricActivation::ActivationType mActivationType;
+
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index fdc28ea..cb1cefb 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -132,7 +132,7 @@
         return mIsActive;
     }
 
-    inline void getActiveMetrics(std::vector<const MetricProducer*>& metrics) const {
+    inline void getActiveMetrics(std::vector<MetricProducer*>& metrics) const {
         for (const auto& metric : mAllMetricProducers) {
             if (metric->isActive()) {
                 metrics.push_back(metric.get());
@@ -140,6 +140,12 @@
         }
     }
 
+    inline void prepForShutDown(int64_t currentTimeNs) {
+        for (const auto& metric : mAllMetricProducers) {
+            metric->prepActiveForBootIfNecessary(currentTimeNs);
+        }
+    }
+
     void setActiveMetrics(ActiveConfig config, int64_t currentTimeNs);
 
 private:
@@ -271,6 +277,7 @@
     FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 
     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
+    FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 1bd3ef2..ac6c27a 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -361,7 +361,57 @@
         invalidateCurrentBucket();
         return;
     }
-    const int64_t pullDelayNs = getElapsedRealtimeNs() - timestampNs;
+
+    accumulateEvents(allData, timestampNs, timestampNs);
+}
+
+int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
+    return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
+}
+
+void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
+                                       bool pullSuccess, int64_t originalPullTimeNs) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mCondition) {
+        if (!pullSuccess) {
+            // If the pull failed, we won't be able to compute a diff.
+            invalidateCurrentBucket();
+            return;
+        }
+
+        // For scheduled pulled data, the effective event time is snap to the nearest
+        // bucket end. In the case of waking up from a deep sleep state, we will
+        // attribute to the previous bucket end. If the sleep was long but not very long, we
+        // will be in the immediate next bucket. Previous bucket may get a larger number as
+        // we pull at a later time than real bucket end.
+        // If the sleep was very long, we skip more than one bucket before sleep. In this case,
+        // if the diff base will be cleared and this new data will serve as new diff base.
+        int64_t bucketEndTime = calcPreviousBucketEndTime(originalPullTimeNs) - 1;
+        StatsdStats::getInstance().noteBucketBoundaryDelayNs(
+                mMetricId, originalPullTimeNs - bucketEndTime);
+        accumulateEvents(allData, originalPullTimeNs, bucketEndTime);
+
+        // We can probably flush the bucket. Since we used bucketEndTime when calling
+        // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
+        flushIfNeededLocked(originalPullTimeNs);
+
+    } else {
+        VLOG("No need to commit data on condition false.");
+    }
+}
+
+void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData, 
+                                           int64_t originalPullTimeNs, int64_t eventElapsedTimeNs) {
+    bool isEventLate = eventElapsedTimeNs < mCurrentBucketStartTimeNs;
+    if (isEventLate) {
+        VLOG("Skip bucket end pull due to late arrival: %lld vs %lld",
+             (long long)eventElapsedTimeNs, (long long)mCurrentBucketStartTimeNs);
+        StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+        invalidateCurrentBucket();
+        return;
+    }
+
+    const int64_t pullDelayNs = getElapsedRealtimeNs() - originalPullTimeNs;
     StatsdStats::getInstance().notePullDelay(mPullTagId, pullDelayNs);
     if (pullDelayNs > mMaxPullDelayNs) {
         ALOGE("Pull finish too late for atom %d, longer than %lld", mPullTagId,
@@ -373,75 +423,33 @@
         return;
     }
 
-    if (timestampNs < mCurrentBucketStartTimeNs) {
-        // The data will be skipped in onMatchedLogEventInternalLocked, but we don't want to report
-        // for every event, just the pull
-        StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+    if (allData.size() == 0) {
+        VLOG("Data pulled is empty");
+        StatsdStats::getInstance().noteEmptyData(mPullTagId);
     }
 
+    mMatchedMetricDimensionKeys.clear();
     for (const auto& data : allData) {
-        // make a copy before doing and changes
         LogEvent localCopy = data->makeCopy();
-        localCopy.setElapsedTimestampNs(timestampNs);
         if (mEventMatcherWizard->matchLogEvent(localCopy, mWhatMatcherIndex) ==
             MatchingState::kMatched) {
+            localCopy.setElapsedTimestampNs(eventElapsedTimeNs);
             onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
         }
     }
-    mHasGlobalBase = true;
-}
-
-int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
-    return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
-}
-
-void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
-                                       bool pullSuccess) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (mCondition) {
-        if (!pullSuccess) {
-            // If the pull failed, we won't be able to compute a diff.
-            invalidateCurrentBucket();
-            return;
-        }
-
-        if (allData.size() == 0) {
-            VLOG("Data pulled is empty");
-            StatsdStats::getInstance().noteEmptyData(mPullTagId);
-            return;
-        }
-        // For scheduled pulled data, the effective event time is snap to the nearest
-        // bucket end. In the case of waking up from a deep sleep state, we will
-        // attribute to the previous bucket end. If the sleep was long but not very long, we
-        // will be in the immediate next bucket. Previous bucket may get a larger number as
-        // we pull at a later time than real bucket end.
-        // If the sleep was very long, we skip more than one bucket before sleep. In this case,
-        // if the diff base will be cleared and this new data will serve as new diff base.
-        int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
-        int64_t bucketEndTime = calcPreviousBucketEndTime(realEventTime) - 1;
-        bool isEventLate = bucketEndTime < mCurrentBucketStartTimeNs;
-        if (isEventLate) {
-            VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
-                 (long long)mCurrentBucketStartTimeNs);
-            StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
-        }
-
-        for (const auto& data : allData) {
-            LogEvent localCopy = data->makeCopy();
-            if (mEventMatcherWizard->matchLogEvent(localCopy, mWhatMatcherIndex) ==
-                MatchingState::kMatched) {
-                localCopy.setElapsedTimestampNs(bucketEndTime);
-                onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
+    // If the new pulled data does not contains some keys we track in our intervals, we need to
+    // reset the base.
+    for (auto& slice : mCurrentSlicedBucket) {
+        bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first) 
+                != mMatchedMetricDimensionKeys.end();
+        if (!presentInPulledData) {
+            for (auto& interval : slice.second) {
+                interval.hasBase = false;
             }
         }
-        mHasGlobalBase = true;
-
-        // We can probably flush the bucket. Since we used bucketEndTime when calling
-        // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
-        flushIfNeededLocked(realEventTime);
-    } else {
-        VLOG("No need to commit data on condition false.");
     }
+    mMatchedMetricDimensionKeys.clear();
+    mHasGlobalBase = true;
 }
 
 void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
@@ -539,6 +547,7 @@
              (long long)mCurrentBucketStartTimeNs);
         return;
     }
+    mMatchedMetricDimensionKeys.insert(eventKey);
 
     flushIfNeededLocked(eventTimeNs);
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 0cfefa9..d1c2315 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -52,7 +52,7 @@
 
     // Process data pulled on bucket boundary.
     void onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& data,
-                      bool pullSuccess) override;
+                      bool pullSuccess, int64_t originalPullTimeNs) override;
 
     // ValueMetric needs special logic if it's a pulled atom.
     void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
@@ -116,6 +116,9 @@
     // Value fields for matching.
     std::vector<Matcher> mFieldMatchers;
 
+    // Value fields for matching.
+    std::set<MetricDimensionKey> mMatchedMetricDimensionKeys;
+
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
 
@@ -160,6 +163,9 @@
 
     void pullAndMatchEventsLocked(const int64_t timestampNs);
 
+    void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData, 
+                          int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
+
     ValueBucket buildPartialBucket(int64_t bucketEndTime,
                                    const std::vector<Interval>& intervals);
     void initCurrentSlicedBucket();
@@ -242,6 +248,10 @@
     FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
     FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded);
     FRIEND_TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange);
+    FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled);
+    FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged);
+    FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary);
+    FRIEND_TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 180a1ae..463b5a0 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -725,6 +725,8 @@
             ALOGE("Invalid metric tracker index.");
             return false;
         }
+        allMetricProducers[metricTrackerIndex]->setActivationType(
+                metric_activation.activation_type());
         metricsWithActivation.push_back(metricTrackerIndex);
         for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
             const EventActivation& activation = metric_activation.event_activation(j);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 73aab48..6a07a3f 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -419,6 +419,8 @@
       optional int64 condition_change_in_next_bucket = 6;
       optional int64 invalidated_bucket = 7;
       optional int64 bucket_dropped = 8;
+      optional int64 min_bucket_boundary_delay_ns = 9;
+      optional int64 max_bucket_boundary_delay_ns = 10;
     }
     repeated AtomMetricStats atom_metric_stats = 17;
 
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index f76a9ad..aa8cfc5 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -80,6 +80,8 @@
 const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
 const int FIELD_ID_INVALIDATED_BUCKET = 7;
 const int FIELD_ID_BUCKET_DROPPED = 8;
+const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
+const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
 
 namespace {
 
@@ -500,6 +502,10 @@
                        (long long)pair.second.invalidatedBucket);
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_DROPPED,
                        (long long)pair.second.bucketDropped);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS,
+                       (long long)pair.second.minBucketBoundaryDelayNs);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS,
+                       (long long)pair.second.maxBucketBoundaryDelayNs);
     protoOutput->end(token);
 }
 
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 9d3a669..5c6d548 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -379,6 +379,13 @@
 message MetricActivation {
   optional int64 metric_id = 1;
 
+  enum ActivationType {
+      UNKNOWN = 0;
+      ACTIVATE_IMMEDIATELY = 1;
+      ACTIVATE_ON_BOOT = 2;
+  }
+  optional ActivationType activation_type = 3;
+
   repeated EventActivation event_activation = 2;
 }
 
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 6e4b2c8..42cac0c 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -17,32 +17,67 @@
 #include "Log.h"
 
 #include "IncidentdReporter.h"
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
 
 #include <android/os/IIncidentManager.h>
 #include <android/os/IncidentReportArgs.h>
+#include <android/util/ProtoOutputStream.h>
 #include <binder/IBinder.h>
 #include <binder/IServiceManager.h>
 
+#include <vector>
+
 namespace android {
 namespace os {
 namespace statsd {
 
+using android::util::ProtoOutputStream;
+using std::vector;
+
+using util::FIELD_TYPE_MESSAGE;
+using util::FIELD_TYPE_INT32;
+using util::FIELD_TYPE_INT64;
+
+// field ids in IncidentHeaderProto
+const int FIELD_ID_ALERT_ID = 1;
+const int FIELD_ID_CONFIG_KEY = 3;
+const int FIELD_ID_CONFIG_KEY_UID = 1;
+const int FIELD_ID_CONFIG_KEY_ID = 2;
+
+namespace {
+void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uint8_t>* protoData) {
+    ProtoOutputStream headerProto;
+    headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
+    uint64_t token =
+            headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
+    headerProto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_KEY_UID, configKey.GetUid());
+    headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId());
+    headerProto.end(token);
+
+    protoData->resize(headerProto.size());
+    size_t pos = 0;
+    auto iter = headerProto.data();
+    while (iter.readBuffer() != NULL) {
+        size_t toRead = iter.currentToRead();
+        std::memcpy(&((*protoData)[pos]), iter.readBuffer(), toRead);
+        pos += toRead;
+        iter.rp()->move(toRead);
+    }
+}
+}  // namespace
+
 bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
                             const ConfigKey& configKey) {
     if (config.section_size() == 0) {
         VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id,
-            configKey.GetUid(), (long long) configKey.GetId());
+             configKey.GetUid(), (long long)configKey.GetId());
         return false;
     }
 
     IncidentReportArgs incidentReport;
 
-    android::os::IncidentHeaderProto header;
-    header.set_alert_id(rule_id);
-    header.mutable_config_key()->set_uid(configKey.GetUid());
-    header.mutable_config_key()->set_id(configKey.GetId());
-    incidentReport.addHeader(header);
+    vector<uint8_t> protoData;
+    getProtoData(rule_id, configKey, &protoData);
+    incidentReport.addHeader(protoData);
 
     for (int i = 0; i < config.section_size(); i++) {
         incidentReport.addSection(config.section(i));
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 64008b5..60df165 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -574,6 +574,127 @@
     EXPECT_EQ(timeBase2 + ttl6 - activation1006.ttl_ns, activation1003.activation_ns);
 }
 
+TEST(StatsLogProcessorTest, TestActivationOnBoot) {
+    int uid = 1111;
+
+    // Setup a simple config, no activation
+    StatsdConfig config1;
+    config1.set_id(12341);
+    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+
+    long metricId1 = 1234561;
+    long metricId2 = 1234562;
+    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 metric1Activation = config1.add_metric_activation();
+    metric1Activation->set_metric_id(metricId1);
+    metric1Activation->set_activation_type(MetricActivation::ACTIVATE_ON_BOOT);
+    auto metric1ActivationTrigger = metric1Activation->add_event_activation();
+    metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+    metric1ActivationTrigger->set_ttl_seconds(100);
+
+    ConfigKey cfgKey1(uid, 12341);
+    long timeBase1 = 1;
+    sp<StatsLogProcessor> processor =
+            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+
+    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());
+
+    auto metricIt = metricsManager1->mAllMetricProducers.begin();
+    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+        if ((*metricIt)->getMetricId() == metricId1) {
+            break;
+        }
+    }
+    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+    auto& metricProducer1 = *metricIt;
+    EXPECT_FALSE(metricProducer1->isActive());
+
+    metricIt = metricsManager1->mAllMetricProducers.begin();
+    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+        if ((*metricIt)->getMetricId() == metricId2) {
+            break;
+        }
+    }
+    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+    auto& metricProducer2 = *metricIt;
+    EXPECT_TRUE(metricProducer2->isActive());
+
+    const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
+    EXPECT_EQ(100 * NS_PER_SEC, activation1.ttl_ns);
+    EXPECT_EQ(0, activation1.activation_ns);
+    EXPECT_EQ(kNotActive, activation1.state);
+
+    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+    processor->OnLogEvent(event.get());
+
+    EXPECT_FALSE(metricProducer1->isActive());
+    EXPECT_EQ(0, activation1.activation_ns);
+    EXPECT_EQ(kActiveOnBoot, activation1.state);
+
+    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+
+    processor->WriteMetricsActivationToDisk(shutDownTime);
+    EXPECT_TRUE(metricProducer1->isActive());
+    int64_t ttl1 = metricProducer1->getRemainingTtlNs(shutDownTime);
+    EXPECT_EQ(100 * NS_PER_SEC, ttl1);
+
+    long timeBase2 = 1000;
+    sp<StatsLogProcessor> processor2 =
+            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+
+    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+    it = processor2->mMetricsManagers.find(cfgKey1);
+    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+    auto& metricsManager1001 = it->second;
+    EXPECT_TRUE(metricsManager1001->isActive());
+
+    metricIt = metricsManager1001->mAllMetricProducers.begin();
+    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+        if ((*metricIt)->getMetricId() == metricId1) {
+            break;
+        }
+    }
+    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+    auto& metricProducer1001 = *metricIt;
+    EXPECT_FALSE(metricProducer1001->isActive());
+
+    metricIt = metricsManager1001->mAllMetricProducers.begin();
+    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+        if ((*metricIt)->getMetricId() == metricId2) {
+            break;
+        }
+    }
+    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+    auto& metricProducer1002 = *metricIt;
+    EXPECT_TRUE(metricProducer1002->isActive());
+
+    const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
+    EXPECT_EQ(100 * NS_PER_SEC, activation1001.ttl_ns);
+    EXPECT_EQ(0, activation1001.activation_ns);
+    EXPECT_EQ(kNotActive, activation1001.state);
+
+    processor2->LoadMetricsActivationFromDisk();
+
+    EXPECT_TRUE(metricProducer1001->isActive());
+    EXPECT_EQ(timeBase2 + ttl1 - activation1001.ttl_ns, activation1001.activation_ns);
+}
+
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 1725160..6286823 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -133,7 +133,7 @@
     event->init();
     allData.push_back(event);
 
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
@@ -151,7 +151,7 @@
     event2->write(25);
     event2->init();
     allData.push_back(event2);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
     EXPECT_EQ(INT, it->mValue.getType());
@@ -305,7 +305,7 @@
     event->write(1);
     event->init();
     allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
@@ -328,7 +328,7 @@
     event->write(3);
     event->init();
     allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -371,7 +371,7 @@
     event->write(1);
     event->init();
     allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
                          ->second.front()
@@ -440,7 +440,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
@@ -541,7 +541,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true);
+    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
@@ -590,7 +590,7 @@
     event1->write(13);
     event1->init();
 
-    gaugeProducer.onDataPulled({event1}, /** succeed */ true);
+    gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
@@ -604,7 +604,7 @@
     event2->write(15);
     event2->init();
 
-    gaugeProducer.onDataPulled({event2}, /** succeed */ true);
+    gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
@@ -619,7 +619,7 @@
     event3->write(26);
     event3->init();
 
-    gaugeProducer.onDataPulled({event3}, /** succeed */ true);
+    gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
                            ->second.front()
@@ -633,7 +633,7 @@
             std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
     event4->write("some value");
     event4->init();
-    gaugeProducer.onDataPulled({event4}, /** succeed */ true);
+    gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
 }
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 91b98ec..ae3cdbc 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -160,7 +160,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -178,7 +178,7 @@
     event->write(23);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -198,7 +198,7 @@
     event->write(36);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
@@ -265,7 +265,7 @@
     event->write(2);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** success */ true);
+    valueProducer.onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
 
     // Partial buckets created in 2nd bucket.
     valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
@@ -327,7 +327,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
@@ -346,7 +346,7 @@
     event->write(23);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // No new data seen, so data has been cleared.
     EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
 
@@ -363,7 +363,7 @@
     event->write(36);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
@@ -412,7 +412,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -428,7 +428,7 @@
     event->write(10);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -445,7 +445,7 @@
     event->write(36);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasBase);
@@ -493,7 +493,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -509,7 +509,7 @@
     event->write(10);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -524,7 +524,7 @@
     event->write(36);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasBase);
@@ -599,7 +599,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
@@ -710,7 +710,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
@@ -725,7 +725,7 @@
     event->write(150);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(20L,
@@ -764,7 +764,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
@@ -1068,7 +1068,7 @@
     event->init();
     allData.push_back(event);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -1086,7 +1086,7 @@
     event->write(23);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
@@ -1107,7 +1107,7 @@
     event->write(36);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     // startUpdated:false sum:12
@@ -1195,7 +1195,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(false, curInterval.hasBase);
@@ -1291,7 +1291,7 @@
     EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
-    // Now the alarm is delivered, but it is considered late, it has no effect
+    // Now the alarm is delivered, but it is considered late, the bucket is invalidated.
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
     shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
@@ -1299,10 +1299,10 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(false, curInterval.hasBase);
     EXPECT_EQ(130, curInterval.base.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(20, curInterval.value.long_value);
@@ -1752,7 +1752,7 @@
     allData.push_back(event1);
     allData.push_back(event2);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(true, interval1.hasBase);
     EXPECT_EQ(11, interval1.base.long_value);
@@ -1842,7 +1842,7 @@
     allData.push_back(event1);
     allData.push_back(event2);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(true, interval1.hasBase);
     EXPECT_EQ(11, interval1.base.long_value);
@@ -1871,7 +1871,7 @@
     event1->write(5);
     event1->init();
     allData.push_back(event1);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
 
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(true, interval2.hasBase);
@@ -1893,7 +1893,7 @@
     event2->write(5);
     event2->init();
     allData.push_back(event2);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
 
     EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(true, interval2.hasBase);
@@ -1968,7 +1968,7 @@
     allData.push_back(event1);
     allData.push_back(event2);
 
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(true, interval1.hasBase);
     EXPECT_EQ(11, interval1.base.long_value);
@@ -2000,7 +2000,7 @@
     event1->write(5);
     event1->init();
     allData.push_back(event1);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
 
 	// Only one interval left. One was trimmed.
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
@@ -2018,7 +2018,7 @@
     event1->write(14);
     event1->init();
     allData.push_back(event1);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
 
     interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(true, interval2.hasBase);
@@ -2078,7 +2078,7 @@
     EXPECT_EQ(false, curInterval.hasValue);
 
     vector<shared_ptr<LogEvent>> allData;
-    valueProducer.onDataPulled(allData, /** succeed */ false);
+    valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     EXPECT_EQ(false, curInterval.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
@@ -2179,7 +2179,7 @@
     valueProducer.mCondition = true;
 
     vector<shared_ptr<LogEvent>> allData;
-    valueProducer.onDataPulled(allData, /** succeed */ false);
+    valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
     EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.onConditionChanged(false, bucketStartTimeNs + 1);
@@ -2361,7 +2361,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
 
     // This will fail and should invalidate the whole bucket since we do not have all the data
     // needed to compute the metric value when the screen was on.
@@ -2375,7 +2375,7 @@
     event2->write(140);
     event2->init();
     allData.push_back(event2);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
     
@@ -2446,7 +2446,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ false);
+    valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
 
     valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
@@ -2458,7 +2458,7 @@
     event2->write(140);
     event2->init();
     allData.push_back(event2);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
 
     valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
     
@@ -2529,7 +2529,7 @@
     event->write(110);
     event->init();
     allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
 
     // This will fail and should invalidate the whole bucket since we do not have all the data
     // needed to compute the metric value when the screen was on.
@@ -2543,7 +2543,7 @@
     event2->write(140);
     event2->init();
     allData.push_back(event2);
-    valueProducer.onDataPulled(allData, /** succeed */ false);
+    valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
 
     valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
     
@@ -2557,6 +2557,268 @@
     EXPECT_EQ(false, valueProducer.mHasGlobalBase);
 }
 
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // Start bucket.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+
+    // Bucket 2 start.
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(tagId);
+    event->write(110);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+
+    // Bucket 3 empty.
+    allData.clear();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+    event2->init();
+    allData.push_back(event2);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+    // Data has been trimmed.
+    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+}
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_condition(StringToId("SCREEN_ON"));
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // First onConditionChanged
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval& curInterval =
+            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+    // Empty pull.
+    valueProducer.onConditionChanged(false, bucketStartTimeNs + 10);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_condition(StringToId("SCREEN_ON"));
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // First onConditionChanged
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(1);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(2);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(5);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+    valueProducer.onConditionChanged(false, bucketStartTimeNs + 11);
+    valueProducer.onConditionChanged(true, bucketStartTimeNs + 12);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval& curInterval =
+            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+    // End of bucket
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    // Data is empty, base should be reset.
+    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(5, curInterval.base.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+}
+
+
+TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.mutable_dimensions_in_what()->set_field(tagId);
+    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+    metric.set_condition(StringToId("SCREEN_ON"));
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // First onConditionChanged
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(1);
+                event->write(1);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+    // End of bucket
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(2);
+    event->write(2);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+    // Key 1 should be reset since in not present in the most pull.
+    EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+    auto iterator = valueProducer.mCurrentSlicedBucket.begin();
+    EXPECT_EQ(true, iterator->second[0].hasBase);
+    EXPECT_EQ(2, iterator->second[0].base.long_value);
+    EXPECT_EQ(false, iterator->second[0].hasValue);
+    iterator++;
+    EXPECT_EQ(false, iterator->second[0].hasBase);
+    EXPECT_EQ(1, iterator->second[0].base.long_value);
+    EXPECT_EQ(false, iterator->second[0].hasValue);
+
+    EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-greylist-max-p.txt
index 7840b18..4c643e1 100644
--- a/config/hiddenapi-greylist-max-p.txt
+++ b/config/hiddenapi-greylist-max-p.txt
@@ -48,6 +48,8 @@
 Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
 Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
 Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
+Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats;
 Landroid/view/IWindowManager;->setInTouchMode(Z)V
 Landroid/view/IWindowManager;->showStrictModeViolation(Z)V
 Lcom/android/internal/R$styleable;->AndroidManifestActivityAlias:[I
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index a0d8a12..010e447 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1474,8 +1474,6 @@
 Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
 Landroid/view/IAppTransitionAnimationSpecsFuture$Stub;-><init>()V
 Landroid/view/IDockedStackListener$Stub;-><init>()V
-Landroid/view/IGraphicsStats$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/view/IGraphicsStats$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IGraphicsStats;
 Landroid/view/IRecentsAnimationController;->finish(Z)V
 Landroid/view/IRecentsAnimationController;->screenshotTask(I)Landroid/app/ActivityManager$TaskSnapshot;
 Landroid/view/IRecentsAnimationController;->setAnimationTargetsBehindSystemBars(Z)V
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 5814e69..ce71998 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -26,6 +26,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Insets;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
 import android.os.RemoteException;
@@ -84,6 +85,8 @@
     /** The ActivityView is only allowed to contain one task. */
     private final boolean mSingleTaskInstance;
 
+    private Insets mForwardedInsets;
+
     @UnsupportedAppUsage
     public ActivityView(Context context) {
         this(context, null /* attrs */);
@@ -369,11 +372,13 @@
                 .build();
 
         try {
+            // TODO: Find a way to consolidate these calls to the server.
             wm.reparentDisplayContent(displayId, mRootSurfaceControl);
             wm.dontOverrideDisplayInfo(displayId);
             if (mSingleTaskInstance) {
                 mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
             }
+            wm.setForwardedInsets(displayId, mForwardedInsets);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
@@ -454,6 +459,24 @@
     }
 
     /**
+     * Set forwarded insets on the virtual display.
+     *
+     * @see IWindowManager#setForwardedInsets
+     */
+    public void setForwardedInsets(Insets insets) {
+        mForwardedInsets = insets;
+        if (mVirtualDisplay == null) {
+            return;
+        }
+        try {
+            final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+            wm.setForwardedInsets(mVirtualDisplay.getDisplay().getDisplayId(), mForwardedInsets);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * A task change listener that detects background color change of the topmost stack on our
      * virtual display and updates the background of the surface view. This background will be shown
      * when surface view is resized, but the app hasn't drawn its content in new size yet.
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index f522d71..17f645d 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -125,7 +125,7 @@
     public static final int RESULT_ALTERNATE = 1;
 
     /**
-     * @deprecated see {@link BiometricPrompt.Builder#setEnableFallback(boolean)}
+     * @deprecated see {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)}
      *
      * Get an intent to prompt the user to confirm credentials (pin, pattern, password or biometrics
      * if enrolled) for the current user of the device. The caller is expected to launch this
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 028e3ef..dc4f343 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8243,6 +8243,7 @@
 
         private void buildIntoRemoteViewContent(RemoteViews remoteViews,
                 RemoteViews customContent, TemplateBindResult result) {
+            int childIndex = -1;
             if (customContent != null) {
                 // Need to clone customContent before adding, because otherwise it can no longer be
                 // parceled independently of remoteViews.
@@ -8250,7 +8251,11 @@
                 remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress);
                 remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */);
                 remoteViews.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED);
+                childIndex = 0;
             }
+            remoteViews.setIntTag(R.id.notification_main_column,
+                    com.android.internal.R.id.notification_custom_view_index_tag,
+                    childIndex);
             // also update the end margin if there is an image
             Resources resources = mBuilder.mContext.getResources();
             int endMargin = resources.getDimensionPixelSize(
diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING
index 78ec8a1..65859c7 100644
--- a/core/java/android/app/TEST_MAPPING
+++ b/core/java/android/app/TEST_MAPPING
@@ -6,5 +6,13 @@
     {
       "path": "frameworks/base/services/core/java/com/android/server/wm"
     }
+  ],
+  "presubmit": [
+      {
+        "name": "CtsFragmentTestCases"
+      },
+      {
+        "name": "CtsFragmentTestCasesSdk26"
+      }
   ]
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3ff6973..f8d9553 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9628,7 +9628,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param enabled {@code true} to enable the backup service, {@code false} to disable it.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * @throws SecurityException if {@code admin} is not a device owner or a profile owner.
      */
     public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) {
         throwIfParentInstance("setBackupServiceEnabled");
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index fa2a6a1..04d5c5a 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -131,20 +131,20 @@
      * TODO: STOPSHIP: Make name of required roles public API
      * @hide
      */
-    public static final String ROLE_CAR_MODE_DIALER_APP = "android.app.role.CAR_MODE_DIALER_APP";
+    public static final String ROLE_CAR_MODE_DIALER = "android.app.role.CAR_MODE_DIALER";
 
     /**
-     * The name of the proxy calling role.
+     * The name of the call redirection role.
      * <p>
-     * A proxy calling app provides a means to re-write the phone number for an outgoing call to
-     * place the call through a proxy calling service.
+     * A call redirection app provides a means to re-write the phone number for an outgoing call to
+     * place the call through a call redirection service.
      *
      * @see android.telecom.CallRedirectionService
      *
      * TODO: STOPSHIP: Make name of required roles public API
      * @hide
      */
-    public static final String ROLE_PROXY_CALLING_APP = "android.app.role.PROXY_CALLING_APP";
+    public static final String ROLE_CALL_REDIRECTION = "android.app.role.CALL_REDIRECTION";
 
     /**
      * The name of the call screening and caller id role.
@@ -154,7 +154,7 @@
      * TODO: STOPSHIP: Make name of required roles public API
      * @hide
      */
-    public static final String ROLE_CALL_SCREENING_APP = "android.app.role.CALL_SCREENING_APP";
+    public static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING";
 
     /**
      * The name of the call companion app role.
@@ -170,7 +170,7 @@
      * TODO: STOPSHIP: Make name of required roles public API
      * @hide
      */
-    public static final String ROLE_CALL_COMPANION_APP = "android.app.role.CALL_COMPANION_APP";
+    public static final String ROLE_CALL_COMPANION = "android.app.role.CALL_COMPANION";
 
     /**
      * The name of the assistant app role.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6e52b33..eaf6c5a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -715,7 +715,6 @@
             INSTALL_FORCE_PERMISSION_PROMPT,
             INSTALL_INSTANT_APP,
             INSTALL_DONT_KILL_APP,
-            INSTALL_FORCE_SDK,
             INSTALL_FULL_APP,
             INSTALL_ALLOCATE_AGGRESSIVE,
             INSTALL_VIRTUAL_PRELOAD,
@@ -816,15 +815,6 @@
     public static final int INSTALL_DONT_KILL_APP = 0x00001000;
 
     /**
-     * Flag parameter for {@link #installPackage} to indicate that this package is an
-     * upgrade to a package that refers to the SDK via release letter or is targeting an SDK via
-     * release letter that the current build does not support.
-     *
-     * @hide
-     */
-    public static final int INSTALL_FORCE_SDK = 0x00002000;
-
-    /**
      * Flag parameter for {@link #installPackage} to indicate that this package is
      * to be installed as a heavy weight app. This is fundamentally the opposite of
      * {@link #INSTALL_INSTANT_APP}.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5020a94..96b6eb52 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -839,7 +839,6 @@
     public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
     public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
     public static final int PARSE_ENFORCE_CODE = 1 << 6;
-    public static final int PARSE_FORCE_SDK = 1 << 7;
     public static final int PARSE_CHATTY = 1 << 31;
 
     @IntDef(flag = true, prefix = { "PARSE_" }, value = {
@@ -847,7 +846,6 @@
             PARSE_COLLECT_CERTIFICATES,
             PARSE_ENFORCE_CODE,
             PARSE_EXTERNAL_STORAGE,
-            PARSE_FORCE_SDK,
             PARSE_IGNORE_PROCESSES,
             PARSE_IS_SYSTEM_DIR,
             PARSE_MUST_BE_APK,
@@ -2684,8 +2682,6 @@
      * @param platformSdkCodenames array of allowed pre-release SDK codenames
      *                             for this platform
      * @param outError output array to populate with error, if applicable
-     * @param forceCurrentDev if development target code is not available, use the current
-     *                        development version by default.
      * @return the targetSdkVersion to use at runtime, or -1 if the package is
      *         not compatible with this platform
      * @hide Exposed for unit testing only.
@@ -2693,7 +2689,7 @@
     @TestApi
     public static int computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
             @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
-            @NonNull String[] outError, boolean forceCurrentDev) {
+            @NonNull String[] outError) {
         // If it's a release SDK, return the version number unmodified.
         if (targetCode == null) {
             return targetVers;
@@ -2701,7 +2697,7 @@
 
         // If it's a pre-release SDK and the codename matches this platform, it
         // definitely targets this SDK.
-        if (matchTargetCode(platformSdkCodenames, targetCode) || forceCurrentDev) {
+        if (matchTargetCode(platformSdkCodenames, targetCode)) {
             return Build.VERSION_CODES.CUR_DEVELOPMENT;
         }
 
@@ -2768,9 +2764,8 @@
             return null;
         }
 
-        boolean defaultToCurrentDevBranch = (flags & PARSE_FORCE_SDK) != 0;
         final int targetSdkVersion = computeTargetSdkVersion(targetVers,
-                targetCode, SDK_CODENAMES, outError, defaultToCurrentDevBranch);
+                targetCode, SDK_CODENAMES, outError);
         if (targetSdkVersion < 0) {
             return null;
         }
diff --git a/core/java/android/debug/AdbManagerInternal.java b/core/java/android/debug/AdbManagerInternal.java
index 4469f0f..51eb7fc 100644
--- a/core/java/android/debug/AdbManagerInternal.java
+++ b/core/java/android/debug/AdbManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.debug;
 
+import java.io.File;
+
 /**
  * This class allows the control of ADB-related functions that should only be called from the system
  * server.
@@ -41,4 +43,14 @@
      * Returns {@code true} if ADB debugging is enabled.
      */
     public abstract boolean isAdbEnabled();
+
+    /**
+     * Returns the file that contains all of the ADB keys used by the device.
+     */
+    public abstract File getAdbKeysFile();
+
+    /**
+     * Returns the file that contains all of the ADB keys and their last used time.
+     */
+    public abstract File getAdbTempKeysFile();
 }
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index c814b7c..1cb7eb0 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -17,6 +17,7 @@
 package android.hardware.biometrics;
 
 import android.annotation.UnsupportedAppUsage;
+import android.app.KeyguardManager;
 
 
 /**
@@ -126,6 +127,13 @@
     int BIOMETRIC_ERROR_NEGATIVE_BUTTON = 13;
 
     /**
+     * The device does not have pin, pattern, or password set up. See
+     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link KeyguardManager#isDeviceSecure()}
+     */
+    int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index b708ef1..459ec62 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -16,6 +16,7 @@
 
 package android.hardware.biometrics;
 
+import android.app.KeyguardManager;
 import android.hardware.face.FaceManager;
 
 /**
@@ -134,6 +135,13 @@
     public static final int FACE_ERROR_NEGATIVE_BUTTON = 13;
 
     /**
+     * The device does not have pin, pattern, or password set up. See
+     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link KeyguardManager#isDeviceSecure()}
+     */
+    public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+    /**
      * @hide
      */
     public static final int FACE_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 041b2e6..6cbab47 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -17,6 +17,7 @@
 package android.hardware.biometrics;
 
 import android.annotation.UnsupportedAppUsage;
+import android.app.KeyguardManager;
 import android.hardware.fingerprint.FingerprintManager;
 
 /**
@@ -119,6 +120,14 @@
     public static final int FINGERPRINT_ERROR_NEGATIVE_BUTTON = 13;
 
     /**
+     * The device does not have pin, pattern, or password set up. See
+     * {@link BiometricPrompt.Builder#setAllowDeviceCredential(boolean)} and
+     * {@link KeyguardManager#isDeviceSecure()}
+     * @hide
+     */
+    public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index d569a78..baf972b 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -23,6 +23,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Binder;
@@ -80,7 +81,7 @@
     /**
      * @hide
      */
-    public static final String KEY_ENABLE_FALLBACK = "enable_fallback";
+    public static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";
 
     /**
      * Error/help message will show for this amount of time.
@@ -203,7 +204,8 @@
          * "Cancel" button, but may be also used to show an alternative method for authentication,
          * such as screen that asks for a backup password.
          *
-         * Note that this should not be set if {@link #setEnableFallback(boolean)} is set to true.
+         * Note that this should not be set if {@link #setAllowDeviceCredential(boolean)
+         * is set to true.
          *
          * @param text
          * @return
@@ -250,7 +252,10 @@
 
         /**
          * The user will first be prompted to authenticate with biometrics, but also given the
-         * option to authenticate with their device PIN, pattern, or password.
+         * option to authenticate with their device PIN, pattern, or password. Developers should
+         * first check {@link KeyguardManager#isDeviceSecure()} before enabling this. If the device
+         * is not secure, {@link BiometricPrompt#BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL} will be
+         * returned in {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}}
          *
          * Note that {@link #setNegativeButton(CharSequence, Executor,
          * DialogInterface.OnClickListener)} should not be set if this is set to true.
@@ -259,8 +264,8 @@
          *               credentials (PIN, pattern, or password).
          * @return
          */
-        public Builder setEnableFallback(boolean enable) {
-            mBundle.putBoolean(KEY_ENABLE_FALLBACK, enable);
+        public Builder setAllowDeviceCredential(boolean enable) {
+            mBundle.putBoolean(KEY_ALLOW_DEVICE_CREDENTIAL, enable);
             return this;
         }
 
@@ -273,7 +278,7 @@
             final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
             final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
             final boolean useDefaultTitle = mBundle.getBoolean(KEY_USE_DEFAULT_TITLE);
-            final boolean enableFallback = mBundle.getBoolean(KEY_ENABLE_FALLBACK);
+            final boolean enableFallback = mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);
 
             if (TextUtils.isEmpty(title) && !useDefaultTitle) {
                 throw new IllegalArgumentException("Title must be set and non-empty");
@@ -281,7 +286,7 @@
                 throw new IllegalArgumentException("Negative text must be set and non-empty");
             } else if (!TextUtils.isEmpty(negative) && enableFallback) {
                 throw new IllegalArgumentException("Can't have both negative button behavior"
-                        + " and fallback enabled");
+                        + " and device credential enabled");
             }
             return new BiometricPrompt(mContext, mBundle, mPositiveButtonInfo, mNegativeButtonInfo);
         }
@@ -541,8 +546,8 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        if (mBundle.getBoolean(KEY_ENABLE_FALLBACK)) {
-            throw new IllegalArgumentException("Fallback not supported with crypto");
+        if (mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
+            throw new IllegalArgumentException("Device credential not supported with crypto");
         }
         authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
     }
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index e4336d1..a20e2bf 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -54,7 +54,7 @@
 
     // TODO(b/123378871): Remove when moved.
     // CDCA needs to send results to BiometricService if it was invoked using BiometricPrompt's
-    // setEnableFallback method, since there's no way for us to intercept onActivityResult.
+    // setAllowDeviceCredential method, since there's no way for us to intercept onActivityResult.
     // CDCA is launched from BiometricService (startActivityAsUser) instead of *ForResult.
     void onConfirmDeviceCredentialSuccess();
     // TODO(b/123378871): Remove when moved.
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index c9a7830..efe24e5 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -565,16 +565,16 @@
      */
     public static String getErrorString(Context context, int errMsg, int vendorCode) {
         switch (errMsg) {
-            case FACE_ERROR_UNABLE_TO_PROCESS:
-                return context.getString(
-                        com.android.internal.R.string.face_error_unable_to_process);
             case FACE_ERROR_HW_UNAVAILABLE:
                 return context.getString(
                         com.android.internal.R.string.face_error_hw_not_available);
-            case FACE_ERROR_NO_SPACE:
-                return context.getString(com.android.internal.R.string.face_error_no_space);
+            case FACE_ERROR_UNABLE_TO_PROCESS:
+                return context.getString(
+                        com.android.internal.R.string.face_error_unable_to_process);
             case FACE_ERROR_TIMEOUT:
                 return context.getString(com.android.internal.R.string.face_error_timeout);
+            case FACE_ERROR_NO_SPACE:
+                return context.getString(com.android.internal.R.string.face_error_no_space);
             case FACE_ERROR_CANCELED:
                 return context.getString(com.android.internal.R.string.face_error_canceled);
             case FACE_ERROR_LOCKOUT:
@@ -629,6 +629,24 @@
                 return context.getString(R.string.face_acquired_poor_gaze);
             case FACE_ACQUIRED_NOT_DETECTED:
                 return context.getString(R.string.face_acquired_not_detected);
+            case FACE_ACQUIRED_TOO_MUCH_MOTION:
+                return context.getString(R.string.face_acquired_too_much_motion);
+            case FACE_ACQUIRED_RECALIBRATE:
+                return context.getString(R.string.face_acquired_recalibrate);
+            case FACE_ACQUIRED_TOO_DIFFERENT:
+                return context.getString(R.string.face_acquired_too_different);
+            case FACE_ACQUIRED_TOO_SIMILAR:
+                return context.getString(R.string.face_acquired_too_similar);
+            case FACE_ACQUIRED_PAN_TOO_EXTREME:
+                return context.getString(R.string.face_acquired_pan_too_extreme);
+            case FACE_ACQUIRED_TILT_TOO_EXTREME:
+                return context.getString(R.string.face_acquired_tilt_too_extreme);
+            case FACE_ACQUIRED_ROLL_TOO_EXTREME:
+                return context.getString(R.string.face_acquired_roll_too_extreme);
+            case FACE_ACQUIRED_FACE_OBSCURED:
+                return context.getString(R.string.face_acquired_obscured);
+            case FACE_ACQUIRED_START:
+                return null;
             case FACE_ACQUIRED_VENDOR: {
                 String[] msgArray = context.getResources().getStringArray(
                         R.array.face_acquired_vendor);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index bb98211..80d404d 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -949,17 +949,17 @@
      */
     public static String getErrorString(Context context, int errMsg, int vendorCode) {
         switch (errMsg) {
+            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
+                return context.getString(
+                        com.android.internal.R.string.fingerprint_error_hw_not_available);
             case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
                 return context.getString(
                     com.android.internal.R.string.fingerprint_error_unable_to_process);
-            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
-                return context.getString(
-                    com.android.internal.R.string.fingerprint_error_hw_not_available);
+            case FINGERPRINT_ERROR_TIMEOUT:
+                return context.getString(com.android.internal.R.string.fingerprint_error_timeout);
             case FINGERPRINT_ERROR_NO_SPACE:
                 return context.getString(
                     com.android.internal.R.string.fingerprint_error_no_space);
-            case FINGERPRINT_ERROR_TIMEOUT:
-                return context.getString(com.android.internal.R.string.fingerprint_error_timeout);
             case FINGERPRINT_ERROR_CANCELED:
                 return context.getString(com.android.internal.R.string.fingerprint_error_canceled);
             case FINGERPRINT_ERROR_LOCKOUT:
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d2ab053..9e97e37 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -526,11 +526,12 @@
                                   @Nullable String packageName,
                                   @Nullable String[] packagesForUid,
                                   @Nullable String[] visibleVols,
+                                  @Nullable String sandboxId,
                                   @Nullable String[] zygoteArgs) {
         return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    packagesForUid, visibleVols, /*useBlastulaPool=*/ true, zygoteArgs);
+                    packagesForUid, visibleVols, sandboxId, /*useBlastulaPool=*/ true, zygoteArgs);
     }
 
     /** @hide */
@@ -547,11 +548,12 @@
                                   @Nullable String packageName,
                                   @Nullable String[] packagesForUid,
                                   @Nullable String[] visibleVols,
+                                  @Nullable String sandboxId,
                                   @Nullable String[] zygoteArgs) {
         return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
-                    packagesForUid, visibleVols, /*useBlastulaPool=*/ false, zygoteArgs);
+                    packagesForUid, visibleVols, sandboxId, /*useBlastulaPool=*/ false, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index e94ad2b..ee3d354 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -324,13 +324,15 @@
                                                   @Nullable String packageName,
                                                   @Nullable String[] packagesForUid,
                                                   @Nullable String[] visibleVols,
+                                                  @Nullable String sandboxId,
                                                   boolean useBlastulaPool,
                                                   @Nullable String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/false,
-                    packageName, packagesForUid, visibleVols, useBlastulaPool, zygoteArgs);
+                    packageName, packagesForUid, visibleVols, sandboxId,
+                    useBlastulaPool, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -541,6 +543,7 @@
                                                       @Nullable String packageName,
                                                       @Nullable String[] packagesForUid,
                                                       @Nullable String[] visibleVols,
+                                                      @Nullable String sandboxId,
                                                       boolean useBlastulaPool,
                                                       @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
@@ -639,6 +642,10 @@
             argsForZygote.add(sb.toString());
         }
 
+        if (sandboxId != null) {
+            argsForZygote.add("--sandbox-id=" + sandboxId);
+        }
+
         argsForZygote.add(processClass);
 
         if (extraArgs != null) {
@@ -1014,7 +1021,7 @@
                     gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
                     abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
                     true /* startChildZygote */, null /* packageName */,
-                    null /* packagesForUid */, null /* visibleVolumes */,
+                    null /* packagesForUid */, null /* visibleVolumes */, null /* sandboxId */,
                     false /* useBlastulaPool */, extraArgs);
         } catch (ZygoteStartFailedEx ex) {
             throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index f521c68..03b2c2c 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -132,4 +132,9 @@
      * @param listener The listener that will be notified on reset events.
      */
     public abstract void addResetListener(ResetListener listener);
+
+    /**
+     * Return the sandboxId for the given package on external storage.
+     */
+    public abstract String getSandboxId(String packageName);
 }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 5ac31dc..41d3cbb 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -72,45 +72,13 @@
     public static final String NAMESPACE_AUTOFILL = "autofill";
 
     /**
-     * ContentCapture-related properties definitions.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface ContentCapture {
-        String NAMESPACE = "content_capture";
-
-        /**
-         * Property used by {@code com.android.server.SystemServer} on start to decide whether
-         * the Content Capture service should be created or not.
-         *
-         * <p>Possible values are:
-         *
-         * <ul>
-         *   <li>If set to {@code default}, it will only be set if the OEM provides and defines the
-         *   service name by overlaying {@code config_defaultContentCaptureService} (this is the
-         *   "default" mode)
-         *   <li>If set to {@code always}, it will always be enabled, even when the resource is not
-         *   overlaid (this is useful during development and to run the CTS tests on AOSP builds).
-         *   <li>Otherwise, it's explicitly disabled (this could work as a "kill switch" so OEMs
-         *   can disable it remotely in case of emergency by setting to something else (like
-         *   {@code "false"}); notice that it's also disabled if the OEM doesn't explicitly set one
-         *   of the values above).
-         * </ul>
-         *
-         * @hide
-         */
-        // TODO(b/121153631): revert back to SERVICE_EXPLICITLY_ENABLED approach
-        String PROPERTY_CONTENTCAPTURE_ENABLED = "enable_contentcapture";
-    }
-
-    /**
      * Namespace for content capture feature used by on-device machine intelligence
      * to provide suggestions in a privacy-safe manner.
      *
      * @hide
      */
     @SystemApi
+    @TestApi
     public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
 
     /**
@@ -154,21 +122,6 @@
     }
 
     /**
-     * Namespace for all runtime related features.
-     *
-     * @hide
-     */
-    @SystemApi
-    public interface Runtime {
-        String NAMESPACE = "runtime";
-
-        /**
-         * Whether or not we use the precompiled layout.
-         */
-        String USE_PRECOMPILED_LAYOUT = "view.precompiled_layout_enabled";
-    }
-
-    /**
      * Namespace for all runtime native related features.
      *
      * @hide
@@ -375,6 +328,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     @RequiresPermission(READ_DEVICE_CONFIG)
     public static String getProperty(String namespace, String name) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 67c8400..0b38420 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -157,10 +157,6 @@
     public static final String PARAM_DELETE_DATA = "deletedata";
 
     /** {@hide} */
-    public static final String PARAM_PRIMARY = "primary";
-    /** {@hide} */
-    public static final String PARAM_SECONDARY = "secondary";
-    /** {@hide} */
     public static final String PARAM_INCLUDE_PENDING = "includePending";
     /** {@hide} */
     public static final String PARAM_INCLUDE_TRASHED = "includeTrashed";
@@ -543,7 +539,9 @@
      * @see MediaStore#setIncludeTrashed(Uri)
      * @see MediaStore#trash(Context, Uri)
      * @see MediaStore#untrash(Context, Uri)
+     * @removed
      */
+    @Deprecated
     public static @NonNull Uri setIncludeTrashed(@NonNull Uri uri) {
         return uri.buildUpon().appendQueryParameter(PARAM_INCLUDE_TRASHED, "1").build();
     }
@@ -580,14 +578,7 @@
      */
     public static @NonNull Uri createPending(@NonNull Context context,
             @NonNull PendingParams params) {
-        final Uri.Builder builder = params.insertUri.buildUpon();
-        if (!TextUtils.isEmpty(params.primaryDirectory)) {
-            builder.appendQueryParameter(PARAM_PRIMARY, params.primaryDirectory);
-        }
-        if (!TextUtils.isEmpty(params.secondaryDirectory)) {
-            builder.appendQueryParameter(PARAM_SECONDARY, params.secondaryDirectory);
-        }
-        return context.getContentResolver().insert(builder.build(), params.insertValues);
+        return context.getContentResolver().insert(params.insertUri, params.insertValues);
     }
 
     /**
@@ -610,10 +601,6 @@
         public final Uri insertUri;
         /** {@hide} */
         public final ContentValues insertValues;
-        /** {@hide} */
-        public String primaryDirectory;
-        /** {@hide} */
-        public String secondaryDirectory;
 
         /**
          * Create parameters that describe a pending media item.
@@ -655,7 +642,11 @@
          * @see MediaColumns#PRIMARY_DIRECTORY
          */
         public void setPrimaryDirectory(@Nullable String primaryDirectory) {
-            this.primaryDirectory = primaryDirectory;
+            if (primaryDirectory == null) {
+                this.insertValues.remove(MediaColumns.PRIMARY_DIRECTORY);
+            } else {
+                this.insertValues.put(MediaColumns.PRIMARY_DIRECTORY, primaryDirectory);
+            }
         }
 
         /**
@@ -668,7 +659,11 @@
          * @see MediaColumns#SECONDARY_DIRECTORY
          */
         public void setSecondaryDirectory(@Nullable String secondaryDirectory) {
-            this.secondaryDirectory = secondaryDirectory;
+            if (secondaryDirectory == null) {
+                this.insertValues.remove(MediaColumns.SECONDARY_DIRECTORY);
+            } else {
+                this.insertValues.put(MediaColumns.SECONDARY_DIRECTORY, secondaryDirectory);
+            }
         }
 
         /**
@@ -797,7 +792,9 @@
      * @see MediaStore#setIncludeTrashed(Uri)
      * @see MediaStore#trash(Context, Uri)
      * @see MediaStore#untrash(Context, Uri)
+     * @removed
      */
+    @Deprecated
     public static void trash(@NonNull Context context, @NonNull Uri uri) {
         trash(context, uri, 48 * DateUtils.HOUR_IN_MILLIS);
     }
@@ -815,7 +812,9 @@
      * @see MediaStore#setIncludeTrashed(Uri)
      * @see MediaStore#trash(Context, Uri)
      * @see MediaStore#untrash(Context, Uri)
+     * @removed
      */
+    @Deprecated
     public static void trash(@NonNull Context context, @NonNull Uri uri,
             @DurationMillisLong long timeoutMillis) {
         if (timeoutMillis < 0) {
@@ -837,7 +836,9 @@
      * @see MediaStore#setIncludeTrashed(Uri)
      * @see MediaStore#trash(Context, Uri)
      * @see MediaStore#untrash(Context, Uri)
+     * @removed
      */
+    @Deprecated
     public static void untrash(@NonNull Context context, @NonNull Uri uri) {
         final ContentValues values = new ContentValues();
         values.put(MediaColumns.IS_TRASHED, 0);
@@ -884,7 +885,9 @@
          * hash is calculated.
          * <p>
          * Type: BLOB
+         * @removed
          */
+        @Deprecated
         public static final String HASH = "_hash";
 
         /**
@@ -921,8 +924,22 @@
         public static final String DATE_MODIFIED = "date_modified";
 
         /**
-         * The MIME type of the file
-         * <P>Type: TEXT</P>
+         * The MIME type of the media item.
+         * <p>
+         * This is typically defined based on the file extension of the media
+         * item. However, it may be the value of the {@code format} attribute
+         * defined by the <em>Dublin Core Media Initiative</em> standard,
+         * extracted from any XMP metadata contained within this media item.
+         * <p class="note">
+         * Note: the {@code format} attribute may be ignored if the top-level
+         * MIME type disagrees with the file extension. For example, it's
+         * reasonable for an {@code image/jpeg} file to declare a {@code format}
+         * of {@code image/vnd.google.panorama360+jpg}, but declaring a
+         * {@code format} of {@code audio/ogg} would be ignored.
+         * <p>
+         * This is a read-only column that is automatically computed.
+         * <p>
+         * Type: TEXT
          */
         public static final String MIME_TYPE = "mime_type";
 
@@ -965,7 +982,9 @@
          * @see MediaStore#setIncludeTrashed(Uri)
          * @see MediaStore#trash(Context, Uri)
          * @see MediaStore#untrash(Context, Uri)
+         * @removed
          */
+        @Deprecated
         public static final String IS_TRASHED = "is_trashed";
 
         /**
@@ -974,7 +993,9 @@
          * {@link #IS_PENDING} or {@link #IS_TRASHED}.
          * <p>
          * Type: INTEGER
+         * @removed
          */
+        @Deprecated
         public static final String DATE_EXPIRES = "date_expires";
 
         /**
@@ -991,6 +1012,8 @@
          * Package name that contributed this media. The value may be
          * {@code NULL} if ownership cannot be reliably determined.
          * <p>
+         * This is a read-only column that is automatically computed.
+         * <p>
          * Type: TEXT
          */
         public static final String OWNER_PACKAGE_NAME = "owner_package_name";
@@ -1014,6 +1037,52 @@
          * @see PendingParams#setSecondaryDirectory(String)
          */
         public static final String SECONDARY_DIRECTORY = "secondary_directory";
+
+        /**
+         * The "document ID" GUID as defined by the <em>XMP Media
+         * Management</em> standard, extracted from any XMP metadata contained
+         * within this media item. The value is {@code null} when no metadata
+         * was found.
+         * <p>
+         * Each "document ID" is created once for each new resource. Different
+         * renditions of that resource are expected to have different IDs.
+         * <p>
+         * This is a read-only column that is automatically computed.
+         * <p>
+         * Type: TEXT
+         */
+        public static final String DOCUMENT_ID = "document_id";
+
+        /**
+         * The "instance ID" GUID as defined by the <em>XMP Media
+         * Management</em> standard, extracted from any XMP metadata contained
+         * within this media item. The value is {@code null} when no metadata
+         * was found.
+         * <p>
+         * This "instance ID" changes with each save operation of a specific
+         * "document ID".
+         * <p>
+         * This is a read-only column that is automatically computed.
+         * <p>
+         * Type: TEXT
+         */
+        public static final String INSTANCE_ID = "instance_id";
+
+        /**
+         * The "original document ID" GUID as defined by the <em>XMP Media
+         * Management</em> standard, extracted from any XMP metadata contained
+         * within this media item.
+         * <p>
+         * This "original document ID" links a resource to its original source.
+         * For example, when you save a PSD document as a JPEG, then convert the
+         * JPEG to GIF format, the "original document ID" of both the JPEG and
+         * GIF files is the "document ID" of the original PSD file.
+         * <p>
+         * This is a read-only column that is automatically computed.
+         * <p>
+         * Type: TEXT
+         */
+        public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
     }
 
     /**
@@ -3097,20 +3166,29 @@
 
         final ArrayList<File> res = new ArrayList<>();
         if (VOLUME_INTERNAL.equals(volumeName)) {
-            res.add(new File(Environment.getRootDirectory(), "media"));
-            res.add(new File(Environment.getOemDirectory(), "media"));
-            res.add(new File(Environment.getProductDirectory(), "media"));
+            addCanoncialFile(res, new File(Environment.getRootDirectory(), "media"));
+            addCanoncialFile(res, new File(Environment.getOemDirectory(), "media"));
+            addCanoncialFile(res, new File(Environment.getProductDirectory(), "media"));
         } else {
-            res.add(getVolumePath(volumeName));
+            addCanoncialFile(res, getVolumePath(volumeName));
             final UserManager um = AppGlobals.getInitialApplication()
                     .getSystemService(UserManager.class);
             if (VOLUME_EXTERNAL.equals(volumeName) && um.isDemoUser()) {
-                res.add(Environment.getDataPreloadsMediaDirectory());
+                addCanoncialFile(res, Environment.getDataPreloadsMediaDirectory());
             }
         }
         return res;
     }
 
+    private static void addCanoncialFile(List<File> list, File file) {
+        try {
+            list.add(file.getCanonicalFile());
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to resolve " + file + ": " + e);
+            list.add(file);
+        }
+    }
+
     /**
      * Uri for querying the state of the media scanner.
      */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e95d6046..de84e71 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8289,6 +8289,7 @@
          * The value is boolean (1 or 0).
          * @hide
          */
+        @TestApi
         public static final String NOTIFICATION_BADGING = "notification_badging";
 
         private static final Validator NOTIFICATION_BADGING_VALIDATOR = BOOLEAN_VALIDATOR;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 43de1f8..ff4ee9c 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -27,6 +27,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
@@ -281,7 +282,7 @@
         }
     };
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467)
     public DisplayInfo() {
     }
 
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8ae4757..2ef7c4b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -25,6 +25,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
+import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -380,6 +381,16 @@
     void getStableInsets(int displayId, out Rect outInsets);
 
     /**
+     * Set the forwarded insets on the display.
+     * <p>
+     * This is only used in case a virtual display is displayed on another display that has insets,
+     * and the bounds of the virtual display is overlapping with the insets from the host display.
+     * In that case, the contents on the virtual display won't be placed over the forwarded insets.
+     * Only the owner of the display is permitted to set the forwarded insets on it.
+     */
+    void setForwardedInsets(int displayId, in Insets insets);
+
+    /**
      * Register shortcut key. Shortcut code is packed as:
      * (MetaState << Integer.SIZE) | KeyCode
      * @hide
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 583651d..dd88e3c 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -33,6 +33,7 @@
 import android.view.InsetsState.InsetSide;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
 import android.view.WindowInsets.Type.InsetType;
+import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -165,7 +166,8 @@
             @Nullable @InsetSide SparseIntArray typeSideMap) {
         return state.calculateInsets(frame, false /* isScreenRound */,
                 false /* alwaysConsumerNavBar */, null /* displayCutout */,
-                null /* legacyContentInsets */, null /* legacyStableInsets */, typeSideMap)
+                null /* legacyContentInsets */, null /* legacyStableInsets */,
+                LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, typeSideMap)
                .getInsets(mTypes);
     }
 
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 7ad97a6..2586000 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -112,6 +112,8 @@
 
     private int mPendingTypesToShow;
 
+    private int mLastLegacySoftInputMode;
+
     public InsetsController(ViewRootImpl viewRoot) {
         mViewRoot = viewRoot;
         mAnimCallback = () -> {
@@ -126,13 +128,17 @@
             }
             WindowInsets insets = state.calculateInsets(mFrame, mLastInsets.isRound(),
                     mLastInsets.shouldAlwaysConsumeNavBar(), mLastInsets.getDisplayCutout(),
-                    mLastLegacyContentInsets, mLastLegacyStableInsets,
+                    mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
                     null /* typeSideMap */);
             mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets);
         };
     }
 
     void onFrameChanged(Rect frame) {
+        if (mFrame.equals(frame)) {
+            return;
+        }
+        mViewRoot.notifyInsetsChanged();
         mFrame.set(frame);
     }
 
@@ -160,11 +166,12 @@
     @VisibleForTesting
     public WindowInsets calculateInsets(boolean isScreenRound,
             boolean alwaysConsumeNavBar, DisplayCutout cutout, Rect legacyContentInsets,
-            Rect legacyStableInsets) {
+            Rect legacyStableInsets, int legacySoftInputMode) {
         mLastLegacyContentInsets.set(legacyContentInsets);
         mLastLegacyStableInsets.set(legacyStableInsets);
+        mLastLegacySoftInputMode = legacySoftInputMode;
         mLastInsets = mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout,
-                legacyContentInsets, legacyStableInsets,
+                legacyContentInsets, legacyStableInsets, legacySoftInputMode,
                 null /* typeSideMap */);
         return mLastInsets;
     }
@@ -257,11 +264,21 @@
 
     private void controlWindowInsetsAnimation(@InsetType int types,
             WindowInsetsAnimationControlListener listener, boolean fromIme) {
+        // If the frame of our window doesn't span the entire display, the control API makes very
+        // little sense, as we don't deal with negative insets. So just cancel immediately.
+        if (!mState.getDisplayFrame().equals(mFrame)) {
+            listener.onCancelled();
+            return;
+        }
+        controlAnimationUnchecked(types, listener, mFrame, fromIme);
+    }
+
+    private void controlAnimationUnchecked(@InsetType int types,
+            WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme) {
         if (types == 0) {
             // nothing to animate.
             return;
         }
-
         // TODO: Check whether we already have a controller.
         final ArraySet<Integer> internalTypes = mState.toInternalType(types);
         final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
@@ -285,7 +302,7 @@
         }
 
         final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers,
-                mFrame, mState, listener, typesReady,
+                frame, mState, listener, typesReady,
                 () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this);
         mAnimationControls.add(controller);
     }
@@ -436,6 +453,7 @@
             // nothing to animate.
             return;
         }
+
         WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() {
             @Override
             public void onReady(WindowInsetsAnimationController controller, int types) {
@@ -479,7 +497,10 @@
         // TODO: Instead of clearing this here, properly wire up
         // InsetsAnimationControlImpl.finish() to remove this from mAnimationControls.
         mAnimationControls.clear();
-        controlWindowInsetsAnimation(types, listener, fromIme);
+
+        // Show/hide animations always need to be relative to the display frame, in order that shown
+        // and hidden state insets are correct.
+        controlAnimationUnchecked(types, listener, mState.getDisplayFrame(), fromIme);
     }
 
     private void hideDirectly(@InsetType int types) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 4f809fe6..69f86aa 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -19,6 +19,7 @@
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.WindowInsets.Type.IME;
 import static android.view.WindowInsets.Type.SIZE;
 import static android.view.WindowInsets.Type.indexOf;
 
@@ -34,11 +35,13 @@
 import android.util.SparseIntArray;
 import android.view.WindowInsets.Type;
 import android.view.WindowInsets.Type.InsetType;
+import android.view.WindowManager.LayoutParams;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Objects;
 
 /**
  * Holder for state of system windows that cause window insets for all other windows in the system.
@@ -104,6 +107,11 @@
 
     private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
 
+    /**
+     * The frame of the display these sources are relative to.
+     */
+    private final Rect mDisplayFrame = new Rect();
+
     public InsetsState() {
     }
 
@@ -124,7 +132,7 @@
     public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
             boolean alwaysConsumeNavBar, DisplayCutout cutout,
             @Nullable Rect legacyContentInsets, @Nullable Rect legacyStableInsets,
-            @Nullable @InsetSide SparseIntArray typeSideMap) {
+            int legacySoftInputMode, @Nullable @InsetSide SparseIntArray typeSideMap) {
         Insets[] typeInsetsMap = new Insets[Type.SIZE];
         Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
         boolean[] typeVisibilityMap = new boolean[SIZE];
@@ -140,8 +148,12 @@
             if (source == null) {
                 continue;
             }
-            if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
-                    && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR)) {
+
+            boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
+                    && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR);
+            boolean skipIme = source.getType() == TYPE_IME
+                    && (legacySoftInputMode & LayoutParams.SOFT_INPUT_ADJUST_RESIZE) == 0;
+            if (skipSystemBars || skipIme) {
                 typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible();
                 continue;
             }
@@ -209,6 +221,14 @@
         return mSources.computeIfAbsent(type, InsetsSource::new);
     }
 
+    public void setDisplayFrame(Rect frame) {
+        mDisplayFrame.set(frame);
+    }
+
+    public Rect getDisplayFrame() {
+        return mDisplayFrame;
+    }
+
     /**
      * Modifies the state of this class to exclude a certain type to make it ready for dispatching
      * to the client.
@@ -224,6 +244,7 @@
     }
 
     public void set(InsetsState other, boolean copySources) {
+        mDisplayFrame.set(other.mDisplayFrame);
         mSources.clear();
         if (copySources) {
             for (int i = 0; i < other.mSources.size(); i++) {
@@ -323,6 +344,9 @@
 
         InsetsState state = (InsetsState) o;
 
+        if (!mDisplayFrame.equals(state.mDisplayFrame)) {
+            return false;
+        }
         if (mSources.size() != state.mSources.size()) {
             return false;
         }
@@ -341,7 +365,7 @@
 
     @Override
     public int hashCode() {
-        return mSources.hashCode();
+        return Objects.hash(mDisplayFrame, mSources);
     }
 
     public InsetsState(Parcel in) {
@@ -355,9 +379,10 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mDisplayFrame, flags);
         dest.writeInt(mSources.size());
         for (int i = 0; i < mSources.size(); i++) {
-            dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+            dest.writeParcelable(mSources.valueAt(i), flags);
         }
     }
 
@@ -374,6 +399,7 @@
 
     public void readFromParcel(Parcel in) {
         mSources.clear();
+        mDisplayFrame.set(in.readParcelable(null /* loader */));
         final int size = in.readInt();
         for (int i = 0; i < size; i++) {
             final InsetsSource source = in.readParcelable(null /* loader */);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index c130250..3f18d8b 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -33,8 +33,6 @@
 import android.os.Message;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -53,6 +51,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.util.HashMap;
+import java.util.Objects;
 
 /**
  * Instantiates a layout XML file into its corresponding {@link android.view.View}
@@ -81,6 +80,8 @@
     private static final String TAG = LayoutInflater.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY
+        = "view.precompiled_layout_enabled";
     private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
 
     /** Empty stack trace used to avoid log spam in re-throw exceptions. */
@@ -111,7 +112,12 @@
     // The classloader includes the generated compiled_view.dex file.
     private ClassLoader mPrecompiledClassLoader;
 
-    @UnsupportedAppUsage
+    /**
+     * This is not a public API. Two APIs are now available to alleviate the need to access
+     * this directly: {@link #createView(Context, String, String, AttributeSet)} and
+     * {@link #onCreateView(Context, View, String, AttributeSet)}.
+     */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     final Object[] mConstructorArgs = new Object[2];
 
     @UnsupportedAppUsage
@@ -401,19 +407,8 @@
     }
 
     private void initPrecompiledViews() {
-        // Use the device config if enabled, otherwise default to the system property.
-        String usePrecompiledLayout = DeviceConfig.getProperty(
-                DeviceConfig.Runtime.NAMESPACE,
-                DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT);
-        boolean enabled = false;
-        if (TextUtils.isEmpty(usePrecompiledLayout)) {
-            enabled = SystemProperties.getBoolean(
-                    DeviceConfig.Runtime.USE_PRECOMPILED_LAYOUT,
-                    false);
-        } else {
-            enabled = Boolean.parseBoolean(usePrecompiledLayout);
-        }
-        initPrecompiledViews(enabled);
+        initPrecompiledViews(
+                SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
     }
 
     private void initPrecompiledViews(boolean enablePrecompiledViews) {
@@ -733,11 +728,11 @@
         } while (cl != null);
         return false;
     }
-
     /**
      * Low-level function for instantiating a view by name. This attempts to
      * instantiate a view class of the given <var>name</var> found in this
-     * LayoutInflater's ClassLoader.
+     * LayoutInflater's ClassLoader. To use an explicit Context in the View
+     * constructor, use {@link #createView(Context, String, String, AttributeSet)} instead.
      *
      * <p>
      * There are two things that can happen in an error case: either the
@@ -753,6 +748,37 @@
      */
     public final View createView(String name, String prefix, AttributeSet attrs)
             throws ClassNotFoundException, InflateException {
+        Context context = (Context) mConstructorArgs[0];
+        if (context == null) {
+            context = mContext;
+        }
+        return createView(context, name, prefix, attrs);
+    }
+
+    /**
+     * Low-level function for instantiating a view by name. This attempts to
+     * instantiate a view class of the given <var>name</var> found in this
+     * LayoutInflater's ClassLoader.
+     *
+     * <p>
+     * There are two things that can happen in an error case: either the
+     * exception describing the error will be thrown, or a null will be
+     * returned. You must deal with both possibilities -- the former will happen
+     * the first time createView() is called for a class of a particular name,
+     * the latter every time there-after for that class name.
+     *
+     * @param viewContext The context used as the context parameter of the View constructor
+     * @param name The full name of the class to be instantiated.
+     * @param attrs The XML attributes supplied for this instance.
+     *
+     * @return View The newly instantiated view, or null.
+     */
+    @Nullable
+    public final View createView(@NonNull Context viewContext, @NonNull String name,
+            @Nullable String prefix, @Nullable AttributeSet attrs)
+            throws ClassNotFoundException, InflateException {
+        Objects.requireNonNull(viewContext);
+        Objects.requireNonNull(name);
         Constructor<? extends View> constructor = sConstructorMap.get(name);
         if (constructor != null && !verifyClassLoader(constructor)) {
             constructor = null;
@@ -799,22 +825,21 @@
             }
 
             Object lastContext = mConstructorArgs[0];
-            if (mConstructorArgs[0] == null) {
-                // Fill in the context if not already within inflation.
-                mConstructorArgs[0] = mContext;
-            }
+            mConstructorArgs[0] = viewContext;
             Object[] args = mConstructorArgs;
             args[1] = attrs;
 
-            final View view = constructor.newInstance(args);
-            if (view instanceof ViewStub) {
-                // Use the same context when inflating ViewStub later.
-                final ViewStub viewStub = (ViewStub) view;
-                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+            try {
+                final View view = constructor.newInstance(args);
+                if (view instanceof ViewStub) {
+                    // Use the same context when inflating ViewStub later.
+                    final ViewStub viewStub = (ViewStub) view;
+                    viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
+                }
+                return view;
+            } finally {
+                mConstructorArgs[0] = lastContext;
             }
-            mConstructorArgs[0] = lastContext;
-            return view;
-
         } catch (NoSuchMethodException e) {
             final InflateException ie = new InflateException(attrs.getPositionDescription()
                     + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
@@ -883,6 +908,26 @@
     }
 
     /**
+     * Version of {@link #onCreateView(View, String, AttributeSet)} that also
+     * takes the inflation context.  The default
+     * implementation simply calls {@link #onCreateView(View, String, AttributeSet)}.
+     *
+     * @param viewContext The Context to be used as a constructor parameter for the View
+     * @param parent The future parent of the returned view.  <em>Note that
+     * this may be null.</em>
+     * @param name The fully qualified class name of the View to be create.
+     * @param attrs An AttributeSet of attributes to apply to the View.
+     *
+     * @return View The View created.
+     */
+    @Nullable
+    public View onCreateView(@NonNull Context viewContext, @Nullable View parent,
+            @NonNull String name, @Nullable AttributeSet attrs)
+            throws ClassNotFoundException {
+        return onCreateView(parent, name, attrs);
+    }
+
+    /**
      * Convenience method for calling through to the five-arg createViewFromTag
      * method. This method passes {@code false} for the {@code ignoreThemeAttr}
      * argument and should be used for everything except {@code &gt;include>}
@@ -933,9 +978,9 @@
                 mConstructorArgs[0] = context;
                 try {
                     if (-1 == name.indexOf('.')) {
-                        view = onCreateView(parent, name, attrs);
+                        view = onCreateView(context, parent, name, attrs);
                     } else {
-                        view = createView(name, null, attrs);
+                        view = createView(context, name, null, attrs);
                     }
                 } finally {
                     mConstructorArgs[0] = lastContext;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index b6a4a09..b6c4cbb 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -24,6 +24,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.Matrix;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -1513,7 +1514,7 @@
     }
 
     // Pointer to the native MotionEvent object that contains the actual data.
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private long mNativePtr;
 
     private MotionEvent mNext;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 8028715..1212df0 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -62,6 +62,7 @@
 
 import java.io.Closeable;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 /**
  * Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is
@@ -711,8 +712,10 @@
                 for (int i = 0; i < metadata.size(); ++i) {
                     metaParcel.writeInt(metadata.keyAt(i));
                     metaParcel.writeByteArray(
-                            ByteBuffer.allocate(4).putInt(metadata.valueAt(i)).array());
+                            ByteBuffer.allocate(4).order(ByteOrder.nativeOrder())
+                                    .putInt(metadata.valueAt(i)).array());
                 }
+                metaParcel.setDataPosition(0);
             }
             mNativeObject = nativeCreate(session, name, w, h, format, flags,
                     parent != null ? parent.mNativeObject : 0, metaParcel);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c641552..3f2795b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -23429,7 +23429,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768420)
     protected void internalSetPadding(int left, int top, int right, int bottom) {
         mUserPaddingLeft = left;
         mUserPaddingRight = right;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 156972f..1a782ee 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1887,7 +1887,7 @@
                 mLastWindowInsets = mInsetsController.calculateInsets(
                         mContext.getResources().getConfiguration().isScreenRound(),
                         mAttachInfo.mAlwaysConsumeNavBar, displayCutout,
-                        contentInsets, stableInsets);
+                        contentInsets, stableInsets, mWindowAttributes.softInputMode);
             } else {
                 mLastWindowInsets = new WindowInsets(contentInsets, stableInsets,
                         mContext.getResources().getConfiguration().isScreenRound(),
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 2512b95..634443d 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -66,6 +66,25 @@
      */
     private static final int SYNC_CALLS_TIMEOUT_MS = 5000;
 
+    /**
+     * DeviceConfig property used by {@code com.android.server.SystemServer} on start to decide
+     * whether the Content Capture service should be created or not
+     *
+     * <p>By default it should *NOT* be set (or set to {@code "default"}, so the decision is based
+     * on whether the OEM provides an implementation for the service), but it can be overridden to:
+     *
+     * <ul>
+     *   <li>Provide a "kill switch" so OEMs can disable it remotely in case of emergency (when
+     *   it's set to {@code "false"}).
+     *   <li>Enable the CTS tests to be run on AOSP builds (when it's set to {@code "true"}).
+     * </ul>
+     *
+     * @hide
+     */
+    @TestApi
+    public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED =
+            "service_explicitly_enabled";
+
     private final Object mLock = new Object();
 
     @NonNull
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index eb945b5..810c967 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -303,6 +303,7 @@
                     Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
                             + getSanitizedString(event.getText()));
                 }
+                // TODO(b/124107816): should call lastEvent.merge(event) instead
                 lastEvent.setText(event.getText());
                 addEvent = false;
             }
@@ -316,7 +317,7 @@
                     Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
                             + lastEvent.getSessionId());
                 }
-                lastEvent.addAutofillId(event.getId());
+                mergeViewsDisappearedEvent(lastEvent, event);
                 addEvent = false;
             }
         }
@@ -364,6 +365,30 @@
         flush(flushReason);
     }
 
+    // TODO(b/124107816): should be ContentCaptureEvent Event.merge(event) instead (which would
+    // replace the addAutofillId() method - we would also need unit tests on ContentCaptureEventTest
+    // to check these scenarios)
+    private void mergeViewsDisappearedEvent(@NonNull ContentCaptureEvent lastEvent,
+            @NonNull ContentCaptureEvent event) {
+        final List<AutofillId> ids = event.getIds();
+        final AutofillId id = event.getId();
+        if (ids != null) {
+            if (id != null) {
+                Log.w(TAG, "got TYPE_VIEW_DISAPPEARED event with both id and ids: " + event);
+            }
+            for (int i = 0; i < ids.size(); i++) {
+                lastEvent.addAutofillId(ids.get(i));
+            }
+            return;
+        }
+        if (id != null) {
+            lastEvent.addAutofillId(id);
+            return;
+        }
+        throw new IllegalArgumentException(
+                "got TYPE_VIEW_DISAPPEARED event with neither id or ids: " + event);
+    }
+
     @UiThread
     private boolean hasStarted() {
         return mState != UNKNOWN_STATE;
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index 602455c..b0e7ad5 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -85,15 +85,16 @@
     }
 
     /**
-     * Returns the first "translate" action found in the {@code classification} object.
+     * Returns the first action found in the {@code classification} object with an intent
+     * action string, {@code intentAction}.
      */
     @Nullable
-    public static RemoteAction findTranslateAction(TextClassification classification) {
+    public static RemoteAction findAction(TextClassification classification, String intentAction) {
         final ArrayList<Intent> actionIntents = getActionsIntents(classification);
         if (actionIntents != null) {
             final int size = actionIntents.size();
             for (int i = 0; i < size; i++) {
-                if (Intent.ACTION_TRANSLATE.equals(actionIntents.get(i).getAction())) {
+                if (intentAction.equals(actionIntents.get(i).getAction())) {
                     return classification.getActions().get(i);
                 }
             }
@@ -102,6 +103,14 @@
     }
 
     /**
+     * Returns the first "translate" action found in the {@code classification} object.
+     */
+    @Nullable
+    public static RemoteAction findTranslateAction(TextClassification classification) {
+        return findAction(classification, Intent.ACTION_TRANSLATE);
+    }
+
+    /**
      * Returns the entity type contained in the {@code extra}.
      */
     @Nullable
diff --git a/core/java/android/view/textclassifier/LegacyIntentFactory.java b/core/java/android/view/textclassifier/LegacyIntentFactory.java
index b6e5b3e2..2d0d032 100644
--- a/core/java/android/view/textclassifier/LegacyIntentFactory.java
+++ b/core/java/android/view/textclassifier/LegacyIntentFactory.java
@@ -182,7 +182,8 @@
         actions.add(new LabeledIntent(
                 context.getString(com.android.internal.R.string.browse),
                 context.getString(com.android.internal.R.string.browse_desc),
-                new Intent(Intent.ACTION_VIEW, Uri.parse(text))
+                new Intent(Intent.ACTION_VIEW)
+                        .setDataAndNormalize(Uri.parse(text))
                         .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
                 LabeledIntent.DEFAULT_REQUEST_CODE));
         return actions;
diff --git a/core/java/android/view/textclassifier/TemplateIntentFactory.java b/core/java/android/view/textclassifier/TemplateIntentFactory.java
index 5278843..95f88c7 100644
--- a/core/java/android/view/textclassifier/TemplateIntentFactory.java
+++ b/core/java/android/view/textclassifier/TemplateIntentFactory.java
@@ -49,20 +49,18 @@
         }
         final List<TextClassifierImpl.LabeledIntent> labeledIntents = new ArrayList<>();
         for (RemoteActionTemplate remoteActionTemplate : remoteActionTemplates) {
-            Intent intent = createIntent(remoteActionTemplate);
-            if (intent == null) {
+            if (!isValidTemplate(remoteActionTemplate)) {
+                Log.w(TAG, "Invalid RemoteActionTemplate skipped.");
                 continue;
             }
-            TextClassifierImpl.LabeledIntent
-                    labeledIntent = new TextClassifierImpl.LabeledIntent(
-                    remoteActionTemplate.title,
-                    remoteActionTemplate.description,
-                    intent,
-                    remoteActionTemplate.requestCode == null
-                            ? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
-                            : remoteActionTemplate.requestCode
-            );
-            labeledIntents.add(labeledIntent);
+            labeledIntents.add(
+                    new TextClassifierImpl.LabeledIntent(
+                            remoteActionTemplate.title,
+                            remoteActionTemplate.description,
+                            createIntent(remoteActionTemplate),
+                            remoteActionTemplate.requestCode == null
+                                    ? TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE
+                                    : remoteActionTemplate.requestCode));
         }
         labeledIntents.forEach(
                 action -> action.getIntent()
@@ -70,29 +68,43 @@
         return labeledIntents;
     }
 
-    @Nullable
-    private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
-        Intent intent = new Intent();
+    private static boolean isValidTemplate(@Nullable RemoteActionTemplate remoteActionTemplate) {
+        if (remoteActionTemplate == null) {
+            Log.w(TAG, "Invalid RemoteActionTemplate: is null");
+            return false;
+        }
+        if (TextUtils.isEmpty(remoteActionTemplate.title)) {
+            Log.w(TAG, "Invalid RemoteActionTemplate: title is null");
+            return false;
+        }
+        if (TextUtils.isEmpty(remoteActionTemplate.description)) {
+            Log.w(TAG, "Invalid RemoteActionTemplate: description is null");
+            return false;
+        }
         if (!TextUtils.isEmpty(remoteActionTemplate.packageName)) {
-            Log.w(TAG, "A RemoteActionTemplate is skipped as package name is set.");
-            return null;
+            Log.w(TAG, "Invalid RemoteActionTemplate: package name is set");
+            return false;
         }
-        if (!TextUtils.isEmpty(remoteActionTemplate.action)) {
-            intent.setAction(remoteActionTemplate.action);
+        if (TextUtils.isEmpty(remoteActionTemplate.action)) {
+            Log.w(TAG, "Invalid RemoteActionTemplate: intent action not set");
+            return false;
         }
-        Uri data = null;
-        if (!TextUtils.isEmpty(remoteActionTemplate.data)) {
-            data = Uri.parse(remoteActionTemplate.data);
-        }
-        if (data != null || !TextUtils.isEmpty(remoteActionTemplate.type)) {
-            intent.setDataAndType(data, remoteActionTemplate.type);
-        }
-        if (remoteActionTemplate.flags != null) {
-            intent.setFlags(remoteActionTemplate.flags);
-        }
+        return true;
+    }
+
+    private static Intent createIntent(RemoteActionTemplate remoteActionTemplate) {
+        final Intent intent = new Intent(remoteActionTemplate.action);
+        final Uri uri = TextUtils.isEmpty(remoteActionTemplate.data)
+                ? null : Uri.parse(remoteActionTemplate.data).normalizeScheme();
+        final String type = TextUtils.isEmpty(remoteActionTemplate.type)
+                ? null : Intent.normalizeMimeType(remoteActionTemplate.type);
+        intent.setDataAndType(uri, type);
+        intent.setFlags(remoteActionTemplate.flags == null ? 0 : remoteActionTemplate.flags);
         if (remoteActionTemplate.category != null) {
             for (String category : remoteActionTemplate.category) {
-                intent.addCategory(category);
+                if (category != null) {
+                    intent.addCategory(category);
+                }
             }
         }
         intent.putExtras(createExtras(remoteActionTemplate.extras));
@@ -105,6 +117,9 @@
         }
         Bundle bundle = new Bundle();
         for (NamedVariant namedVariant : namedVariants) {
+            if (namedVariant == null) {
+                continue;
+            }
             switch (namedVariant.getType()) {
                 case NamedVariant.TYPE_INT:
                     bundle.putInt(namedVariant.getName(), namedVariant.getInt());
diff --git a/core/java/android/webkit/OWNERS b/core/java/android/webkit/OWNERS
index 00e540a..b33da57 100644
--- a/core/java/android/webkit/OWNERS
+++ b/core/java/android/webkit/OWNERS
@@ -1,3 +1,4 @@
 changwan@google.com
+ntfschr@google.com
 tobiasjs@google.com
 torne@google.com
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6039350..2171fc5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -61,6 +61,7 @@
 import android.view.autofill.AutofillValue;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.view.inspector.InspectableProperty;
 import android.view.textclassifier.TextClassifier;
 import android.widget.AbsoluteLayout;
 
@@ -1239,6 +1240,7 @@
      *
      * @return the URL for the current page
      */
+    @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
     public String getUrl() {
         checkThread();
@@ -1254,6 +1256,7 @@
      *
      * @return the URL that was originally requested for the current page
      */
+    @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
     public String getOriginalUrl() {
         checkThread();
@@ -1266,6 +1269,7 @@
      *
      * @return the title for the current page
      */
+    @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
     public String getTitle() {
         checkThread();
@@ -1278,6 +1282,7 @@
      *
      * @return the favicon for the current page
      */
+    @InspectableProperty(hasAttributeId = false)
     public Bitmap getFavicon() {
         checkThread();
         return mProvider.getFavicon();
@@ -1300,6 +1305,7 @@
      *
      * @return the progress for the current page between 0 and 100
      */
+    @InspectableProperty(hasAttributeId = false)
     public int getProgress() {
         checkThread();
         return mProvider.getProgress();
@@ -1310,6 +1316,7 @@
      *
      * @return the height of the HTML content
      */
+    @InspectableProperty(hasAttributeId = false)
     @ViewDebug.ExportedProperty(category = "webview")
     public int getContentHeight() {
         checkThread();
@@ -2276,6 +2283,11 @@
      *
      * @return the requested renderer priority policy.
      */
+    @InspectableProperty(hasAttributeId = false, enumMapping = {
+            @InspectableProperty.EnumMap(name = "waived", value = RENDERER_PRIORITY_WAIVED),
+            @InspectableProperty.EnumMap(name = "bound", value = RENDERER_PRIORITY_BOUND),
+            @InspectableProperty.EnumMap(name = "important", value = RENDERER_PRIORITY_IMPORTANT)
+    })
     @RendererPriority
     public int getRendererRequestedPriority() {
         return mProvider.getRendererRequestedPriority();
@@ -2288,6 +2300,7 @@
      * @return whether this WebView requests a priority of
      * {@link #RENDERER_PRIORITY_WAIVED} when not visible.
      */
+    @InspectableProperty(hasAttributeId = false)
     public boolean getRendererPriorityWaivedWhenNotVisible() {
         return mProvider.getRendererPriorityWaivedWhenNotVisible();
     }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 542df45..9d7a482 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -338,7 +338,7 @@
      * The data set used to store unused views that should be reused during the next layout
      * to avoid creating new ones
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769398)
     final RecycleBin mRecycler = new RecycleBin();
 
     /**
@@ -421,7 +421,7 @@
      * One of TOUCH_MODE_REST, TOUCH_MODE_DOWN, TOUCH_MODE_TAP, TOUCH_MODE_SCROLL, or
      * TOUCH_MODE_DONE_WAITING
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769413)
     int mTouchMode = TOUCH_MODE_REST;
 
     /**
@@ -634,7 +634,7 @@
     /**
      * Helper object that renders and controls the fast scroll thumb.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768941)
     private FastScroller mFastScroll;
 
     /**
@@ -700,7 +700,7 @@
     /**
      * Maximum distance to overfling during edge effects
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769379)
     int mOverflingDistance;
 
     // These two EdgeGlows are always set and used together.
@@ -708,15 +708,23 @@
 
     /**
      * Tracks the state of the top edge glow.
+     *
+     * Even though this field is practically final, we cannot make it final because there are apps
+     * setting it via reflection and they need to keep working until they target Q.
      */
-    @UnsupportedAppUsage
-    private EdgeEffect mEdgeGlowTop;
+    @NonNull
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769408)
+    private EdgeEffect mEdgeGlowTop = new EdgeEffect(mContext);
 
     /**
      * Tracks the state of the bottom edge glow.
+     *
+     * Even though this field is practically final, we cannot make it final because there are apps
+     * setting it via reflection and they need to keep working until they target Q.
      */
-    @UnsupportedAppUsage
-    private EdgeEffect mEdgeGlowBottom;
+    @NonNull
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768444)
+    private EdgeEffect mEdgeGlowBottom = new EdgeEffect(mContext);
 
     /**
      * An estimate of how many pixels are between the top of the list and
@@ -923,21 +931,6 @@
         mDensityScale = getContext().getResources().getDisplayMetrics().density;
     }
 
-    @Override
-    public void setOverScrollMode(int mode) {
-        if (mode != OVER_SCROLL_NEVER) {
-            if (mEdgeGlowTop == null) {
-                Context context = getContext();
-                mEdgeGlowTop = new EdgeEffect(context);
-                mEdgeGlowBottom = new EdgeEffect(context);
-            }
-        } else {
-            mEdgeGlowTop = null;
-            mEdgeGlowBottom = null;
-        }
-        super.setOverScrollMode(mode);
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -3772,7 +3765,7 @@
     }
 
     private void invalidateTopGlow() {
-        if (mEdgeGlowTop == null) {
+        if (!shouldDisplayEdgeEffects()) {
             return;
         }
         final boolean clipToPadding = getClipToPadding();
@@ -3783,7 +3776,7 @@
     }
 
     private void invalidateBottomGlow() {
-        if (mEdgeGlowBottom == null) {
+        if (!shouldDisplayEdgeEffects()) {
             return;
         }
         final boolean clipToPadding = getClipToPadding();
@@ -4208,7 +4201,7 @@
 
         setPressed(false);
 
-        if (mEdgeGlowTop != null) {
+        if (shouldDisplayEdgeEffects()) {
             mEdgeGlowTop.onRelease();
             mEdgeGlowBottom.onRelease();
         }
@@ -4233,6 +4226,10 @@
         }
     }
 
+    private boolean shouldDisplayEdgeEffects() {
+        return getOverScrollMode() != OVER_SCROLL_NEVER;
+    }
+
     private void onTouchCancel() {
         switch (mTouchMode) {
         case TOUCH_MODE_OVERSCROLL:
@@ -4258,7 +4255,7 @@
             recycleVelocityTracker();
         }
 
-        if (mEdgeGlowTop != null) {
+        if (shouldDisplayEdgeEffects()) {
             mEdgeGlowTop.onRelease();
             mEdgeGlowBottom.onRelease();
         }
@@ -4379,7 +4376,7 @@
     @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
-        if (mEdgeGlowTop != null) {
+        if (shouldDisplayEdgeEffects()) {
             final int scrollY = mScrollY;
             final boolean clipToPadding = getClipToPadding();
             final int width;
@@ -4616,7 +4613,7 @@
      *
      * @param newState The new scroll state.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769710)
     void reportScrollStateChange(int newState) {
         if (newState != mLastScrollState) {
             if (mOnScrollListener != null) {
@@ -5159,7 +5156,7 @@
      * @param incrementalDeltaY Change in deltaY from the previous event.
      * @return true if we're already at the beginning/end of the list and have nothing to do.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051739)
     boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
         final int childCount = getChildCount();
         if (childCount == 0) {
@@ -6371,7 +6368,7 @@
     }
 
     private void finishGlows() {
-        if (mEdgeGlowTop != null) {
+        if (shouldDisplayEdgeEffects()) {
             mEdgeGlowTop.finish();
             mEdgeGlowBottom.finish();
         }
@@ -6478,6 +6475,76 @@
     }
 
     /**
+     * Sets the edge effect color for both top and bottom edge effects.
+     *
+     * @param color The color for the edge effects.
+     * @see #setTopEdgeEffectColor(int)
+     * @see #setBottomEdgeEffectColor(int)
+     * @see #getTopEdgeEffectColor()
+     * @see #getBottomEdgeEffectColor()
+     */
+    public void setEdgeEffectColor(@ColorInt int color) {
+        setTopEdgeEffectColor(color);
+        setBottomEdgeEffectColor(color);
+    }
+
+    /**
+     * Sets the bottom edge effect color.
+     *
+     * @param color The color for the bottom edge effect.
+     * @see #setTopEdgeEffectColor(int)
+     * @see #setEdgeEffectColor(int)
+     * @see #getTopEdgeEffectColor()
+     * @see #getBottomEdgeEffectColor()
+     */
+    public void setBottomEdgeEffectColor(@ColorInt int color) {
+        mEdgeGlowBottom.setColor(color);
+        invalidateBottomGlow();
+    }
+
+    /**
+     * Sets the top edge effect color.
+     *
+     * @param color The color for the top edge effect.
+     * @see #setBottomEdgeEffectColor(int)
+     * @see #setEdgeEffectColor(int)
+     * @see #getTopEdgeEffectColor()
+     * @see #getBottomEdgeEffectColor()
+     */
+    public void setTopEdgeEffectColor(@ColorInt int color) {
+        mEdgeGlowTop.setColor(color);
+        invalidateTopGlow();
+    }
+
+    /**
+     * Returns the top edge effect color.
+     *
+     * @return The top edge effect color.
+     * @see #setEdgeEffectColor(int)
+     * @see #setTopEdgeEffectColor(int)
+     * @see #setBottomEdgeEffectColor(int)
+     * @see #getBottomEdgeEffectColor()
+     */
+    @ColorInt
+    public int getTopEdgeEffectColor() {
+        return mEdgeGlowTop.getColor();
+    }
+
+    /**
+     * Returns the bottom edge effect color.
+     *
+     * @return The bottom edge effect color.
+     * @see #setEdgeEffectColor(int)
+     * @see #setTopEdgeEffectColor(int)
+     * @see #setBottomEdgeEffectColor(int)
+     * @see #getTopEdgeEffectColor()
+     */
+    @ColorInt
+    public int getBottomEdgeEffectColor() {
+        return mEdgeGlowBottom.getColor();
+    }
+
+    /**
      * Sets the recycler listener to be notified whenever a View is set aside in
      * the recycler for later reuse. This listener can be used to free resources
      * associated to the View.
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index ddff858..c55f7d6 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -21,6 +21,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.database.DataSetObserver;
+import android.os.Build;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -152,7 +153,7 @@
     /**
      * True if the data has changed since the last layout
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768524)
     boolean mDataChanged;
 
     /**
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 7e42862..fa0af78 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -17,14 +17,15 @@
 package android.widget;
 
 import android.annotation.ColorInt;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.BlendMode;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.os.Build;
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -48,6 +49,12 @@
  * {@link #draw(Canvas)} method.</p>
  */
 public class EdgeEffect {
+
+    /**
+     * The default blend mode used by {@link EdgeEffect}.
+     */
+    public static final BlendMode DEFAULT_BLEND_MODE = BlendMode.SRC_ATOP;
+
     @SuppressWarnings("UnusedDeclaration")
     private static final String TAG = "EdgeEffect";
 
@@ -108,7 +115,7 @@
     private float mPullDistance;
 
     private final Rect mBounds = new Rect();
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769450)
     private final Paint mPaint = new Paint();
     private float mRadius;
     private float mBaseGlowScale;
@@ -128,7 +135,7 @@
         a.recycle();
         mPaint.setColor((themeColor & 0xffffff) | 0x33000000);
         mPaint.setStyle(Paint.Style.FILL);
-        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
+        mPaint.setBlendMode(DEFAULT_BLEND_MODE);
         mInterpolator = new DecelerateInterpolator();
     }
 
@@ -302,6 +309,22 @@
     }
 
     /**
+     * Set or clear the blend mode. A blend mode defines how source pixels
+     * (generated by a drawing command) are composited with the destination pixels
+     * (content of the render target).
+     * <p />
+     * Pass null to clear any previous blend mode.
+     * <p />
+     *
+     * @see BlendMode
+     *
+     * @param blendmode May be null. The blend mode to be installed in the paint
+     */
+    public void setBlendMode(@Nullable BlendMode blendmode) {
+        mPaint.setBlendMode(blendmode);
+    }
+
+    /**
      * Return the color of this edge effect in argb.
      * @return The color of this edge effect in argb
      */
@@ -310,6 +333,20 @@
         return mPaint.getColor();
     }
 
+
+    /**
+     * Returns the blend mode. A blend mode defines how source pixels
+     * (generated by a drawing command) are composited with the destination pixels
+     * (content of the render target).
+     * <p />
+     *
+     * @return BlendMode
+     */
+    @Nullable
+    public BlendMode getBlendMode() {
+        return mPaint.getBlendMode();
+    }
+
     /**
      * Draw into the provided canvas. Assumes that the canvas has been rotated
      * accordingly and the size has been set. The effect will be drawn the full
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 705a371..88d9380 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -264,7 +264,7 @@
     private WeakReference<View> mAnchorRoot;
     private boolean mIsAnchorRootAttached;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor;
 
     private final View.OnLayoutChangeListener mOnLayoutChangeListener =
@@ -476,22 +476,39 @@
     }
 
     /**
-     * Sets the bounds used as the epicenter of the enter and exit transitions.
-     * <p>
-     * Transitions use a point or Rect, referred to as the epicenter, to orient
+     * <p>Returns bounds which are used as a center of the enter and exit transitions.<p/>
+     *
+     * <p>Transitions use Rect, referred to as the epicenter, to orient
      * the direction of travel. For popup windows, the anchor view bounds are
-     * used as the default epicenter.
-     * <p>
-     * See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
-     * information about how transition epicenters.
+     * used as the default epicenter.</p>
+     *
+     * <p>See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
+     * information about how transition epicenters work.</p>
+     *
+     * @return bounds relative to anchor view, or {@code null} if not set
+     * @see #setEpicenterBounds(Rect)
+     */
+    @Nullable
+    public Rect getEpicenterBounds() {
+        return mEpicenterBounds;
+    }
+
+    /**
+     * <p>Sets the bounds used as the epicenter of the enter and exit transitions.</p>
+     *
+     * <p>Transitions use Rect, referred to as the epicenter, to orient
+     * the direction of travel. For popup windows, the anchor view bounds are
+     * used as the default epicenter.</p>
+     *
+     * <p>See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
+     * information about how transition epicenters work.</p>
      *
      * @param bounds the epicenter bounds relative to the anchor view, or
      *               {@code null} to use the default epicenter
-     * @see #getTransitionEpicenter()
-     * @hide
+     *
+     * @see #getEpicenterBounds()
      */
-    @UnsupportedAppUsage
-    public void setEpicenterBounds(Rect bounds) {
+    public void setEpicenterBounds(@Nullable Rect bounds) {
         mEpicenterBounds = bounds;
     }
 
@@ -865,12 +882,28 @@
     }
 
     /**
-     * Clip this popup window to the screen, but not to the containing window.
+     * <p>Indicates whether this popup will be clipped to the screen and not to the
+     * containing window<p/>
      *
-     * @param enabled True to clip to the screen.
-     * @hide
+     * @return true if popup will be clipped to the screen instead of the window, false otherwise
+     *
+     * @see #setClipToScreenEnabled(boolean)
      */
-    @UnsupportedAppUsage
+    public boolean isClipToScreenEnabled() {
+        return mClipToScreen;
+    }
+
+    /**
+     * <p>Clip this popup window to the screen, but not to the containing window.</p>
+     *
+     * <p>If the popup is showing, calling this method will take effect only
+     * the next time the popup is shown or through a manual call to one of
+     * the {@link #update()} methods.</p>
+     *
+     * @param enabled true to clip to the screen.
+     *
+     * @see #isClipToScreenEnabled()
+     */
     public void setClipToScreenEnabled(boolean enabled) {
         mClipToScreen = enabled;
     }
@@ -927,7 +960,8 @@
      * for positioning.</p>
      *
      * @return true if the window will always be positioned in screen coordinates.
-     * @hide
+     *
+     * @see #setLayoutInScreenEnabled(boolean)
      */
     public boolean isLayoutInScreenEnabled() {
         return mLayoutInScreen;
@@ -939,9 +973,9 @@
      * This will cause the popup to be positioned in absolute screen coordinates.</p>
      *
      * @param enabled true if the popup should always be positioned in screen coordinates
-     * @hide
+     *
+     * @see #isLayoutInScreenEnabled()
      */
-    @UnsupportedAppUsage
     public void setLayoutInScreenEnabled(boolean enabled) {
         mLayoutInScreen = enabled;
     }
@@ -1021,11 +1055,30 @@
     }
 
     /**
-     * Set whether this window is touch modal or if outside touches will be sent to
-     * other windows behind it.
-     * @hide
+     * <p>Indicates whether outside touches will be sent to this window
+     * or other windows behind it<p/>
+     *
+     * @return true if touches will be sent to this window, false otherwise
+     *
+     * @see #setTouchModal(boolean)
      */
-    @UnsupportedAppUsage
+    public boolean isTouchModal() {
+        return !mNotTouchModal;
+    }
+
+    /**
+     * <p>Set whether this window is touch modal or if outside touches will be sent to
+     * other windows behind it.<p/>
+     *
+     * <p>If the popup is showing, calling this method will take effect only
+     * the next time the popup is shown or through a manual call to one of
+     * the {@link #update()} methods.</p>
+     *
+     * @param touchModal true to sent all outside touches to this window,
+     * false to other windows behind it
+     *
+     * @see #isTouchModal()
+     */
     public void setTouchModal(boolean touchModal) {
         mNotTouchModal = !touchModal;
     }
@@ -1454,7 +1507,7 @@
      *
      * @param p the layout parameters of the popup's content view
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private void invokePopup(WindowManager.LayoutParams p) {
         if (mContext != null) {
             p.packageName = mContext.getPackageName();
@@ -2060,6 +2113,8 @@
      *     <li>{@link #setInputMethodMode(int)}</li>
      *     <li>{@link #setTouchable(boolean)}</li>
      *     <li>{@link #setAnimationStyle(int)}</li>
+     *     <li>{@link #setTouchModal(boolean)} (boolean)}</li>
+     *     <li>{@link #setClipToScreenEnabled(boolean)}</li>
      * </ul>
      */
     public void update() {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 24bc9f1..c360903 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -141,13 +141,13 @@
     private boolean mSmoothScrollingEnabled = true;
 
     private int mTouchSlop;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051125)
     private int mMinimumVelocity;
     private int mMaximumVelocity;
 
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.P, trackingBug = 124050903)
     private int mOverscrollDistance;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.P, trackingBug = 124050903)
     private int mOverflingDistance;
 
     private float mVerticalScrollFactor;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 650a194..52e1748 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6117,8 +6117,6 @@
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteFullWifiLockAcquiredLocked(uid);
-            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
-                    StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -6127,9 +6125,6 @@
                 final WorkChain workChain = workChains.get(i);
                 final int uid = mapUid(workChain.getAttributionUid());
                 noteFullWifiLockAcquiredLocked(uid);
-                StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
-                        workChain.getUids(), workChain.getTags(),
-                        StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON);
             }
         }
     }
@@ -6139,8 +6134,6 @@
         for (int i=0; i<N; i++) {
             final int uid = mapUid(ws.get(i));
             noteFullWifiLockReleasedLocked(uid);
-            StatsLog.write_non_chained(StatsLog.WIFI_LOCK_STATE_CHANGED, ws.get(i), ws.getName(i),
-                    StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
         }
 
         final List<WorkChain> workChains = ws.getWorkChains();
@@ -6149,9 +6142,6 @@
                 final WorkChain workChain = workChains.get(i);
                 final int uid = mapUid(workChain.getAttributionUid());
                 noteFullWifiLockReleasedLocked(uid);
-                StatsLog.write(StatsLog.WIFI_LOCK_STATE_CHANGED,
-                        workChain.getUids(), workChain.getTags(),
-                        StatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF);
             }
         }
     }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 8b669d5..40d7868 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -254,14 +254,14 @@
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
-            String packageName, String[] packagesForUID, String[] visibleVolIDs) {
+            String packageName, String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
         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, packageName,
-                packagesForUID, visibleVolIDs);
+                packagesForUID, visibleVolIDs, sandboxId);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true, runtimeFlags);
@@ -276,7 +276,8 @@
     private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
-            String appDataDir, String packageName, String[] packagesForUID, String[] visibleVolIDs);
+            String appDataDir, String packageName, String[] packagesForUID, String[] visibleVolIDs,
+            String sandboxId);
 
     /**
      * Specialize a Blastula instance.  The current VM must have been started
@@ -302,11 +303,11 @@
     public static void specializeBlastula(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
-            String[] packagesForUID, String[] visibleVolIDs) {
+            String[] packagesForUID, String[] visibleVolIDs, String sandboxId) {
 
         nativeSpecializeBlastula(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                                  niceName, startChildZygote, instructionSet, appDataDir,
-                                 packageName, packagesForUID, visibleVolIDs);
+                                 packageName, packagesForUID, visibleVolIDs, sandboxId);
 
         // Enable tracing as soon as possible for the child process.
         Trace.setTracingEnabled(true, runtimeFlags);
@@ -326,7 +327,7 @@
     private static native void nativeSpecializeBlastula(int uid, int gid, int[] gids,
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, String packageName,
-            String[] packagesForUID, String[] visibleVolIDs);
+            String[] packagesForUID, String[] visibleVolIDs, String sandboxId);
 
     /**
      * Called to do any initialization before starting an application.
@@ -638,7 +639,7 @@
                            args.mRuntimeFlags, rlimits, args.mMountExternal,
                            args.mSeInfo, args.mNiceName, args.mStartChildZygote,
                            args.mInstructionSet, args.mAppDataDir, args.mPackageName,
-                           args.mPackagesForUid, args.mVisibleVolIds);
+                           args.mPackagesForUid, args.mVisibleVolIds, args.mSandboxId);
 
         if (args.mNiceName != null) {
             Process.setArgV0(args.mNiceName);
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 24a08ca..e6bcd37 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -119,6 +119,9 @@
     /** from --visible-vols */
     String[] mVisibleVolIds;
 
+    /** from --sandbox-id */
+    String mSandboxId;
+
     /**
      * Any args after and including the first non-option arg (or after a '--')
      */
@@ -385,6 +388,11 @@
                 mPackagesForUid = arg.substring(arg.indexOf('=') + 1).split(",");
             } else if (arg.startsWith("--visible-vols=")) {
                 mVisibleVolIds = arg.substring(arg.indexOf('=') + 1).split(",");
+            } else if (arg.startsWith("--sandbox-id=")) {
+                if (mSandboxId != null) {
+                    throw new IllegalArgumentException("Duplicate arg specified");
+                }
+                mSandboxId = arg.substring(arg.indexOf('=') + 1);
             } else {
                 break;
             }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4ac7f50..9cf7e27 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,7 +258,7 @@
                 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mPackageName,
-                parsedArgs.mPackagesForUid, parsedArgs.mVisibleVolIds);
+                parsedArgs.mPackagesForUid, parsedArgs.mVisibleVolIds, parsedArgs.mSandboxId);
 
         try {
             if (pid == 0) {
diff --git a/core/jni/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
index b52f137..2abd950 100644
--- a/core/jni/android_opengl_EGL15.cpp
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -194,6 +194,7 @@
     if (obj == NULL){
         jniThrowException(_env, "java/lang/IllegalArgumentException",
                           "Object is set to null.");
+        return nullptr;
     }
 
     jlong handle = _env->CallLongMethod(obj, mid);
@@ -254,6 +255,7 @@
     }
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
     }
     return toEGLHandle(_env, eglsyncClass, eglsyncConstructor, _returnValue);
 }
@@ -335,6 +337,7 @@
     }
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return false;
     }
     return (jboolean)_returnValue;
 }
@@ -381,6 +384,7 @@
     }
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
     }
     return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
 }
@@ -448,6 +452,7 @@
     }
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
     }
     return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
 }
@@ -456,8 +461,11 @@
 static jobject
 android_eglCreatePlatformPixmapSurface
   (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_pixmap_buf, jlongArray attrib_list_ref, jint offset) {
-    jniThrowException(_env, "java/lang/UnsupportedOperationException",
-        "eglCreatePlatformPixmapSurface");
+    if ((true)) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
+            "eglCreatePlatformPixmapSurface");
+        return nullptr;
+    }
     return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
 }
 
@@ -523,6 +531,7 @@
     }
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
+        return nullptr;
     }
     return toEGLHandle(_env, eglimageClass, eglimageConstructor, _returnValue);
 }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0ef4f87..d04db92 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -598,72 +598,80 @@
     return 0;
 }
 
+static void CreateDir(const std::string& dir,
+                      mode_t mode, uid_t uid, gid_t gid,
+                      fail_fn_t fail_fn) {
+    if (TEMP_FAILURE_RETRY(access(dir.c_str(), F_OK)) == 0) {
+        return;
+    } else if (errno != ENOENT) {
+        fail_fn(CREATE_ERROR("Failed to stat %s: %s", dir.c_str(), strerror(errno)));
+    }
+    if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
+        fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
+                dir.c_str(), strerror(errno)));
+    }
+}
+
 static void CreatePkgSandbox(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
     // Create /mnt/user/0/package/<package-name>
     userid_t user_id = multiuser_get_user_id(uid);
     std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
-    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0751, AID_ROOT, AID_ROOT) != 0) {
-        fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
-    }
+    CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
 
     StringAppendF(&pkg_sandbox_dir, "/package");
-    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
-        fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
-    }
+    CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
 
     StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
-    if (fs_prepare_dir(pkg_sandbox_dir.c_str(), 0755, uid, uid) != 0) {
-        fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s", pkg_sandbox_dir.c_str()));
-    }
+    CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
 }
 
 static void BindMount(const std::string& sourceDir, const std::string& targetDir,
                       fail_fn_t fail_fn) {
     if (TEMP_FAILURE_RETRY(mount(sourceDir.c_str(), targetDir.c_str(), nullptr,
-                                 MS_BIND | MS_REC, nullptr)) == -1) {
+                                 MS_BIND, nullptr)) == -1) {
         fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
                              sourceDir.c_str(), targetDir.c_str(), strerror(errno)));
     }
-
-    if (TEMP_FAILURE_RETRY(mount(nullptr, targetDir.c_str(), nullptr,
-                                 MS_SLAVE | MS_REC, nullptr)) == -1) {
-        fail_fn(CREATE_ERROR("Failed to set MS_SLAVE for %s", targetDir.c_str()));
-    }
 }
 
 static void MountPkgSpecificDir(const std::string& mntSourceRoot,
                                 const std::string& mntTargetRoot,
                                 const std::string& packageName,
+                                uid_t uid,
                                 const char* dirName,
                                 fail_fn_t fail_fn) {
     std::string mntSourceDir = StringPrintf("%s/Android/%s/%s",
             mntSourceRoot.c_str(), dirName, packageName.c_str());
+    CreateDir(mntSourceDir, 0755, uid, uid, fail_fn);
+
     std::string mntTargetDir = StringPrintf("%s/Android/%s/%s",
             mntTargetRoot.c_str(), dirName, packageName.c_str());
+    CreateDir(mntTargetDir, 0755, uid, uid, fail_fn);
 
     BindMount(mntSourceDir, mntTargetDir, fail_fn);
 }
 
+
+static void createPkgSpecificDirRoots(const std::string& parentDir,
+                                      bool createSandbox,
+                                      mode_t mode, uid_t uid, gid_t gid,
+                                      fail_fn_t fail_fn) {
+    std::string androidDir = StringPrintf("%s/Android", parentDir.c_str());
+    CreateDir(androidDir, mode, uid, gid, fail_fn);
+    std::vector<std::string> dirs = {"data", "media", "obb"};
+    if (createSandbox) {
+        dirs.push_back("sandbox");
+    }
+    for (auto& dir : dirs) {
+        std::string path = StringPrintf("%s/%s", androidDir.c_str(), dir.c_str());
+        CreateDir(path, mode, uid, gid, fail_fn);
+    }
+}
+
 static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames,
                                    const std::vector<std::string>& volumeLabels,
-                                   bool mountAllObbs, userid_t userId, fail_fn_t fail_fn) {
-    if (volumeLabels.size() > 0) {
-        std::string sandboxDataDir = StringPrintf("/storage/%s", volumeLabels[0].c_str());
-        if (volumeLabels[0] == "emulated") {
-            StringAppendF(&sandboxDataDir, "/%d", userId);
-        }
-        StringAppendF(&sandboxDataDir, "/Android/data/%s", packageNames[0].c_str());
-        struct stat sb;
-        if (TEMP_FAILURE_RETRY(lstat(sandboxDataDir.c_str(), &sb)) == -1) {
-            if (errno == ENOENT) {
-                ALOGD("Sandbox not fully prepared for %s", sandboxDataDir.c_str());
-                return;
-            } else {
-                fail_fn(CREATE_ERROR("Failed to lstat %s: %s",
-                                     sandboxDataDir.c_str(), strerror(errno)));
-            }
-        }
-    }
+                                   bool mountAllObbs, const std::string& sandboxId,
+                                   userid_t userId, uid_t uid, fail_fn_t fail_fn) {
     for (auto& label : volumeLabels) {
         std::string mntSource = StringPrintf("/mnt/runtime/write/%s", label.c_str());
         std::string mntTarget = StringPrintf("/storage/%s", label.c_str());
@@ -672,11 +680,26 @@
             StringAppendF(&mntTarget, "/%d", userId);
         }
 
+        if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) < 0) {
+            ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno));
+            continue;
+        }
+
+        // Create /mnt/runtime/write/emulated/0/Android/{data,media,obb,sandbox}
+        createPkgSpecificDirRoots(mntSource, true, 0700, AID_ROOT, AID_ROOT, fail_fn);
+
+        std::string sandboxSource = StringPrintf("%s/Android/sandbox/%s",
+            mntSource.c_str(), sandboxId.c_str());
+        CreateDir(sandboxSource, 0755, uid, uid, fail_fn);
+        BindMount(sandboxSource, mntTarget, fail_fn);
+
+        // Create /storage/emulated/0/Android/{data,media,obb}
+        createPkgSpecificDirRoots(mntTarget, false, 0755, uid, uid, fail_fn);
         for (auto& package : packageNames) {
-            MountPkgSpecificDir(mntSource, mntTarget, package, "data", fail_fn);
-            MountPkgSpecificDir(mntSource, mntTarget, package, "media", fail_fn);
+            MountPkgSpecificDir(mntSource, mntTarget, package, uid, "data", fail_fn);
+            MountPkgSpecificDir(mntSource, mntTarget, package, uid, "media", fail_fn);
             if (!mountAllObbs) {
-                MountPkgSpecificDir(mntSource, mntTarget, package, "obb", fail_fn);
+                MountPkgSpecificDir(mntSource, mntTarget, package, uid, "obb", fail_fn);
             }
         }
 
@@ -693,7 +716,8 @@
 static void MountEmulatedStorage(uid_t uid, jint mount_mode,
         bool force_mount_namespace, const std::string& package_name,
         const std::vector<std::string>& packages_for_uid,
-        const std::vector<std::string>& visible_vol_ids, fail_fn_t fail_fn) {
+        const std::vector<std::string>& visible_vol_ids, const std::string& sandbox_id,
+        fail_fn_t fail_fn) {
     // See storage config details at http://source.android.com/tech/storage/
 
     String8 storageSource;
@@ -744,7 +768,7 @@
                                      strerror(errno)));
             }
         } else {
-            if (package_name.empty()) {
+            if (package_name.empty() || sandbox_id.empty()) {
                 return;
             }
 
@@ -790,7 +814,7 @@
             // care of by vold later.
             if (sandboxAlreadyCreated) {
                 PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
-                    mount_mode == MOUNT_EXTERNAL_INSTALLER, user_id, fail_fn);
+                    mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
             }
         }
     } else {
@@ -1127,7 +1151,7 @@
                              bool is_child_zygote, jstring managed_instruction_set,
                              jstring managed_app_data_dir, jstring managed_package_name,
                              jobjectArray managed_pacakges_for_uid,
-                             jobjectArray managed_visible_vol_ids) {
+                             jobjectArray managed_visible_vol_ids, jstring managed_sandbox_id) {
   const char* process_name = is_system_server ? "system_server" : "zygote";
   auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
   auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1137,6 +1161,7 @@
   auto instruction_set = extract_fn(managed_instruction_set);
   auto app_data_dir = extract_fn(managed_app_data_dir);
   auto package_name = extract_fn(managed_package_name);
+  auto sandbox_id = extract_fn(managed_sandbox_id);
 
   // Keep capabilities across UID change, unless we're staying root.
   if (uid != 0) {
@@ -1179,7 +1204,7 @@
       value_or(std::vector<std::string>());
 
   MountEmulatedStorage(uid, mount_external, use_native_bridge, package_name.value(),
-                       packages_for_uid, visible_vol_ids, fail_fn);
+                       packages_for_uid, visible_vol_ids, sandbox_id.value_or(""), fail_fn);
 
   // If this zygote isn't root, it won't be able to create a process group,
   // since the directory is owned by root.
@@ -1479,7 +1504,7 @@
         jint mount_external, jstring se_info, jstring nice_name,
         jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
         jstring instruction_set, jstring app_data_dir, jstring package_name,
-        jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+        jobjectArray packages_for_uid, jobjectArray visible_vol_ids, jstring sandbox_id) {
     jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
     if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -1511,7 +1536,7 @@
                        capabilities, capabilities,
                        mount_external, se_info, nice_name, false,
                        is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
-                       package_name, packages_for_uid, visible_vol_ids);
+                       package_name, packages_for_uid, visible_vol_ids, sandbox_id);
     }
     return pid;
 }
@@ -1537,7 +1562,7 @@
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        permitted_capabilities, effective_capabilities,
                        MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
-                       false, nullptr, nullptr, nullptr, nullptr, nullptr);
+                       false, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -1691,14 +1716,15 @@
     jint runtime_flags, jobjectArray rlimits,
     jint mount_external, jstring se_info, jstring nice_name,
     jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir,
-    jstring package_name, jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+    jstring package_name, jobjectArray packages_for_uid, jobjectArray visible_vol_ids,
+    jstring sandbox_id) {
   jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
   SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                    capabilities, capabilities,
                    mount_external, se_info, nice_name, false,
                    is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
-                   package_name, packages_for_uid, visible_vol_ids);
+                   package_name, packages_for_uid, visible_vol_ids, sandbox_id);
 }
 
 /**
@@ -1789,7 +1815,7 @@
     { "nativeSecurityInit", "()V",
       (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
@@ -1804,7 +1830,7 @@
     { "nativeForkBlastula", "(II[I)I",
       (void *) com_android_internal_os_Zygote_nativeForkBlastula },
     { "nativeSpecializeBlastula",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeSpecializeBlastula },
     { "nativeGetSocketFDs", "(Z)V",
       (void *) com_android_internal_os_Zygote_nativeGetSocketFDs },
diff --git a/core/proto/android/hardware/biometrics/enums.proto b/core/proto/android/hardware/biometrics/enums.proto
index 91f2acb..973e3e6 100644
--- a/core/proto/android/hardware/biometrics/enums.proto
+++ b/core/proto/android/hardware/biometrics/enums.proto
@@ -43,4 +43,16 @@
     ACTION_AUTHENTICATE = 2;
     ACTION_ENUMERATE = 3;
     ACTION_REMOVE = 4;
+}
+
+enum IssueEnum {
+    ISSUE_UNKNOWN = 0;
+    // When a biometric HAL has crashed.
+    ISSUE_HAL_DEATH = 1;
+    // When Android Framework has a template that doesn't exist in the HAL. The framework
+    // is expected to remove its template to stay in sync with the HAL.
+    ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK = 2;
+    // When the HAL has a template that doesn't exist in Android Framework. The framework
+    // is expected to notify the HAL to remove this template to stay in sync with the framework.
+    ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL = 3;
 }
\ No newline at end of file
diff --git a/core/proto/android/wifi/enums.proto b/core/proto/android/wifi/enums.proto
new file mode 100644
index 0000000..315c579
--- /dev/null
+++ b/core/proto/android/wifi/enums.proto
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.net.wifi;
+
+option java_outer_classname = "WifiProtoEnums";
+option java_multiple_files = true;
+
+/**
+ * Wifi Lock modes, primarily used in
+ * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiLockManager.java.
+ */
+enum WifiModeEnum {
+    /**
+     * Deprecated.
+     * Wi-Fi will be kept active, and will behave normally.
+     */
+    WIFI_MODE_FULL = 1 [deprecated=true];
+
+    /**
+     * Deprecated.
+     * Wi-Fi will be kept active, but the only operation that will be supported is initiation of
+     * scans, and the subsequent reporting of scan results.
+     */
+    WIFI_MODE_SCAN_ONLY = 2 [deprecated=true];
+
+    /**
+     * Wi-Fi will not go to power save.
+     */
+    WIFI_MODE_FULL_HIGH_PERF = 3;
+
+    /**
+     * Wi-Fi will operate with a priority to achieve low latency.
+     */
+    WIFI_MODE_FULL_LOW_LATENCY = 4;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 07dd26e..34ec92e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2267,7 +2267,7 @@
     <!-- Allows an application to start activities from background
          @hide -->
     <permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
-        android:protectionLevel="signature|privileged|vendorPrivileged|oem" />
+        android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier" />
 
     <!-- @SystemApi Must be required by activities that handle the intent action
          {@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ec53811..a501ae2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1921,8 +1921,6 @@
                cell broadcasting sms, and MMS. -->
     <bool name="config_sms_capable">true</bool>
 
-    <!-- TODO: STOPSHIP(b/110557011): Remove this from framework and overlays as we use
-         config_defaultRoleHolders now. -->
     <!-- Default SMS Application. This will be the default SMS application when
          the phone first boots. The user can then change the default app to one
          of their choosing.
@@ -1930,15 +1928,29 @@
          application is desired.
 
          If this string is empty or the specified package does not exist, then
-         the platform will search for an SMS app and use that (if there is one)-->
+         the platform will search for an SMS app and use that (if there is one)
+
+         Note: This config is deprecated, please use config_defaultSms instead. -->
     <string name="default_sms_application" translatable="false">com.android.messaging</string>
 
-    <!-- Default role holders. This will be an array of roles and package names of their default
-         holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". -->
-    <string-array name="config_defaultRoleHolders" translatable="false">
-        <item>android.app.role.SMS: com.android.messaging</item>
-        <item>android.app.role.DIALER: com.android.phone</item>
-    </string-array>
+    <!-- Default web browser.  This is the package name of the application that will
+         be the default browser when the device first boots.  Afterwards the user
+         can select whatever browser app they wish to use as the default.
+
+         If this string is empty or the specified package does not exist, then
+         the behavior will be as though no app was named as an explicit default.
+
+         Note: This config is deprecated, please use config_defaultBrowser instead. -->
+    <string name="default_browser" translatable="false"></string>
+
+    <!-- The name of the package that will hold the assistant role by default. -->
+    <string name="config_defaultAssistant" translatable="false" />
+    <!-- The name of the package that will hold the browser role by default. -->
+    <string name="config_defaultBrowser" translatable="false">@string/default_browser</string>
+    <!-- The name of the package that will hold the dialer role by default. -->
+    <string name="config_defaultDialer" translatable="false">com.android.phone</string>
+    <!-- The name of the package that will hold the SMS role by default. -->
+    <string name="config_defaultSms" translatable="false">@string/default_sms_application</string>
 
     <!-- Enable/disable default bluetooth profiles:
         HSP_AG, ObexObjectPush, Audio, NAP -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bbe3ff9..ce7995a 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -193,4 +193,7 @@
 
   <!-- A tag used to save the notification action object -->
   <item type="id" name="notification_action_index_tag" />
+
+  <!-- A tag used to save the index where the custom view is stored -->
+  <item type="id" name="notification_custom_view_index_tag" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e6d478a..d5cefc4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2971,6 +2971,14 @@
         <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>
 
     <public-group type="bool" first-id="0x01110000">
@@ -2990,11 +2998,6 @@
         <public name="system_notification_accent_color" />
     </public-group>
 
-    <public-group type="array" first-id="0x01070006">
-      <!-- @hide @TestApi @SystemApi -->
-      <public name="config_defaultRoleHolders" />
-    </public-group>
-
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fadb28f..6d5bd4b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1471,6 +1471,8 @@
     <string name="biometric_not_recognized">Not recognized</string>
     <!-- Message shown when biometric authentication has been canceled [CHAR LIMIT=50] -->
     <string name="biometric_error_canceled">Authentication canceled</string>
+    <!-- Message returned to applications if BiometricPrompt setAllowDeviceCredentials is enabled but no pin, pattern, or password is set. [CHAR LIMIT=NONE] -->
+    <string name="biometric_error_device_not_secured">No pin, pattern, or password set</string>
 
     <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
     <string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
@@ -1512,7 +1514,7 @@
     <!-- Generic error message shown when the user has no enrolled fingerprints -->
     <string name="fingerprint_error_no_fingerprints">No fingerprints enrolled.</string>
     <!-- Generic error message shown when the app requests fingerprint authentication on a device without a sensor -->
-    <string name="fingerprint_error_hw_not_present">This device does not have a fingerprint sensor</string>
+    <string name="fingerprint_error_hw_not_present">This device does not have a fingerprint sensor.</string>
 
     <!-- Template to be used to name enrolled fingerprints by default. -->
     <string name="fingerprint_name_template">Finger <xliff:g id="fingerId" example="1">%d</xliff:g></string>
@@ -1555,8 +1557,22 @@
     <string name="face_acquired_poor_gaze">Please look at the sensor.</string>
     <!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
     <string name="face_acquired_not_detected">No face detected.</string>
-    <!-- Message shown during face acquisition when the face is not kept steady infront of device [CHAR LIMIT=50] -->
-    <string name="face_acquired_not_steady">Keep face steady infront of device.</string>
+    <!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] -->
+    <string name="face_acquired_too_much_motion">Too much motion.</string>
+    <!-- Message shown during face acquisition when the sensor needs to be recalibrated [CHAR LIMIT=50] -->
+    <string name="face_acquired_recalibrate">Please re-enroll your face.</string>
+    <!-- Message shown during face enrollment when a different person's face is detected [CHAR LIMIT=50] -->
+    <string name="face_acquired_too_different">Different face detected.</string>
+    <!-- Message shown during face enrollment when the face is too similar to a previous acquisition [CHAR LIMIT=50] -->
+    <string name="face_acquired_too_similar">Too similar, please change your pose.</string>
+    <!-- Message shown during acqusition when the user's face is turned too far left or right [CHAR LIMIT=50] -->
+    <string name="face_acquired_pan_too_extreme">Please look more directly at the camera.</string>
+    <!-- Message shown during acqusition when the user's face is tilted too high or too low [CHAR LIMIT=50] -->
+    <string name="face_acquired_tilt_too_extreme">Please look more directly at the camera.</string>
+    <!-- Message shown during acquisiton when the user's face is tilted too far left or right [CHAR LIMIT=50] -->
+    <string name="face_acquired_roll_too_extreme">Please straighten your head vertically.</string>
+    <!-- Message shown during acquisition when the user's face is obscured [CHAR LIMIT=50] -->
+    <string name="face_acquired_obscured">Please uncover your face.</string>
     <!-- Array containing custom messages shown during face acquisition from vendor.  Vendor is expected to add and translate these strings -->
     <string-array name="face_acquired_vendor">
     </string-array>
@@ -1580,7 +1596,7 @@
     <!-- Generic error message shown when the user has no enrolled face. [CHAR LIMIT=50] -->
     <string name="face_error_not_enrolled">No face enrolled.</string>
     <!-- Generic error message shown when the app requests face authentication on a device without a sensor. [CHAR LIMIT=60] -->
-    <string name="face_error_hw_not_present">This device does not have a face authentication sensor</string>
+    <string name="face_error_hw_not_present">This device does not have a face authentication sensor.</string>
 
     <!-- Template to be used to name enrolled faces by default. [CHAR LIMIT=10] -->
     <string name="face_name_template">Face <xliff:g id="faceId" example="1">%d</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1da9149..410a8c16 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1034,6 +1034,7 @@
   <java-symbol type="string" name="sipAddressTypeOther" />
   <java-symbol type="string" name="sipAddressTypeWork" />
   <java-symbol type="string" name="default_sms_application" />
+  <java-symbol type="string" name="default_browser" />
   <java-symbol type="string" name="sms_control_message" />
   <java-symbol type="string" name="sms_control_title" />
   <java-symbol type="string" name="sms_control_no" />
@@ -2472,6 +2473,7 @@
   <java-symbol type="string" name="biometric_error_user_canceled" />
   <java-symbol type="string" name="biometric_not_recognized" />
   <java-symbol type="string" name="biometric_error_canceled" />
+  <java-symbol type="string" name="biometric_error_device_not_secured" />
 
   <!-- Fingerprint messages -->
   <java-symbol type="string" name="fingerprint_error_unable_to_process" />
@@ -2521,6 +2523,14 @@
   <java-symbol type="string" name="face_acquired_too_left" />
   <java-symbol type="string" name="face_acquired_poor_gaze" />
   <java-symbol type="string" name="face_acquired_not_detected" />
+  <java-symbol type="string" name="face_acquired_too_much_motion" />
+  <java-symbol type="string" name="face_acquired_recalibrate" />
+  <java-symbol type="string" name="face_acquired_too_different" />
+  <java-symbol type="string" name="face_acquired_too_similar" />
+  <java-symbol type="string" name="face_acquired_pan_too_extreme" />
+  <java-symbol type="string" name="face_acquired_tilt_too_extreme" />
+  <java-symbol type="string" name="face_acquired_roll_too_extreme" />
+  <java-symbol type="string" name="face_acquired_obscured" />
   <java-symbol type="array" name="face_acquired_vendor" />
   <java-symbol type="string" name="face_name_template" />
   <java-symbol type="string" name="face_authenticated_no_confirmation_required" />
@@ -3585,6 +3595,7 @@
   <java-symbol type="bool" name="config_useSmsAppService" />
 
   <java-symbol type="id" name="transition_overlay_view_tag" />
+  <java-symbol type="id" name="notification_custom_view_index_tag" />
 
   <java-symbol type="dimen" name="rounded_corner_radius" />
   <java-symbol type="dimen" name="rounded_corner_radius_top" />
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 300394d..aa0e0cd 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -162,14 +162,13 @@
     }
 
     private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename,
-            boolean isPlatformReleased, int expectedTargetSdk, boolean forceCurrentDev) {
+            boolean isPlatformReleased, int expectedTargetSdk) {
         final String[] outError = new String[1];
         final int result = PackageParser.computeTargetSdkVersion(
                 targetSdkVersion,
                 targetSdkCodename,
                 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE,
-                outError,
-                forceCurrentDev);
+                outError);
 
         assertEquals(result, expectedTargetSdk);
 
@@ -185,28 +184,23 @@
         // Do allow older release targetSdkVersion on pre-release platform.
         // APP: Released API 10
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION);
 
         // Do allow same release targetSdkVersion on pre-release platform.
         // APP: Released API 20
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION);
 
         // Do allow newer release targetSdkVersion on pre-release platform.
         // APP: Released API 30
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION);
 
         // Don't allow older pre-release targetSdkVersion on pre-release platform.
         // APP: Pre-release API 10
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1,
-                false /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
 
 
         // Do allow same pre-release targetSdkVersion on pre-release platform,
@@ -214,27 +208,16 @@
         // APP: Pre-release API 20
         // DEV: Pre-release API 20
         verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false,
-                Build.VERSION_CODES.CUR_DEVELOPMENT, false /* forceCurrentDev */);
+                Build.VERSION_CODES.CUR_DEVELOPMENT);
         verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false,
-                Build.VERSION_CODES.CUR_DEVELOPMENT, false /* forceCurrentDev */);
+                Build.VERSION_CODES.CUR_DEVELOPMENT);
 
 
         // Don't allow newer pre-release targetSdkVersion on pre-release platform.
         // APP: Pre-release API 30
         // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1,
-                false /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1,
-                false /* forceCurrentDev */);
-
-
-        // Force newer pre-release targetSdkVersion to current pre-release platform.
-        // APP: Pre-release API 30
-        // DEV: Pre-release API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false,
-                Build.VERSION_CODES.CUR_DEVELOPMENT, true /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
-                Build.VERSION_CODES.CUR_DEVELOPMENT, true /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
     }
 
     @Test
@@ -242,45 +225,36 @@
         // Do allow older release targetSdkVersion on released platform.
         // APP: Released API 10
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION);
 
         // Do allow same release targetSdkVersion on released platform.
         // APP: Released API 20
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION);
 
         // Do allow newer release targetSdkVersion on released platform.
         // APP: Released API 30
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION);
 
         // Don't allow older pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 10
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1,
-                false /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
+        verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
 
         // Don't allow same pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 20
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1,
-                false /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
+        verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
 
 
         // Don't allow newer pre-release targetSdkVersion on released platform.
         // APP: Pre-release API 30
         // DEV: Released API 20
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1,
-                false /* forceCurrentDev */);
-        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1,
-                false /* forceCurrentDev */);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
+        verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index da81d17..80b1f9c 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -19,6 +19,7 @@
 import static android.view.ImeInsetsSourceConsumer.areEditorsSimilar;
 import static android.view.InsetsState.TYPE_IME;
 
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
@@ -73,7 +74,7 @@
                     false,
                     new DisplayCutout(
                             Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
-                    rect, rect);
+                    rect, rect, SOFT_INPUT_ADJUST_RESIZE);
             mImeConsumer = new ImeInsetsSourceConsumer(
                     new InsetsState(), Transaction::new, mController);
         });
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 6dad6a2..731d564 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -20,10 +20,16 @@
 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.TYPE_TOP_BAR;
 
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.graphics.Insets;
@@ -73,7 +79,7 @@
                     false,
                     new DisplayCutout(
                             Insets.of(10, 10, 10, 10), rect, rect, rect, rect),
-                    rect, rect);
+                    rect, rect, SOFT_INPUT_ADJUST_RESIZE);
         });
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
@@ -95,6 +101,17 @@
     }
 
     @Test
+    public void testFrameDoesntMatchDisplay() {
+        mController.onFrameChanged(new Rect(0, 0, 100, 100));
+        mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200));
+        WindowInsetsAnimationControlListener controlListener =
+                mock(WindowInsetsAnimationControlListener.class);
+        mController.controlWindowInsetsAnimation(0, controlListener);
+        verify(controlListener).onCancelled();
+        verify(controlListener, never()).onReady(any(), anyInt());
+    }
+
+    @Test
     public void testAnimationEndState() {
         InsetsSourceControl[] controls = prepareControls();
         InsetsSourceControl navBar = controls[0];
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 03af67d..bd036b0 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -25,6 +25,8 @@
 import static android.view.InsetsState.TYPE_SIDE_BAR_3;
 import static android.view.InsetsState.TYPE_TOP_BAR;
 
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -37,6 +39,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.SparseIntArray;
 import android.view.WindowInsets.Type;
+import android.view.test.InsetsModeSession;
 
 import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -53,49 +56,70 @@
     private InsetsState mState2 = new InsetsState();
 
     @Test
-    public void testCalculateInsets() {
+    public void testCalculateInsets() throws Exception {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+            mState.getSource(TYPE_TOP_BAR).setVisible(true);
+            mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+            mState.getSource(TYPE_IME).setVisible(true);
+            SparseIntArray typeSideMap = new SparseIntArray();
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                    DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, typeSideMap);
+            assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
+            assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
+            assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
+            assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
+            assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+            assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
+        }
+    }
+
+    @Test
+    public void testCalculateInsets_imeAndNav() throws Exception{
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+            mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+            mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+            mState.getSource(TYPE_IME).setVisible(true);
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                    DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null);
+            assertEquals(100, insets.getStableInsetBottom());
+            assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.systemBars()));
+            assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
+            assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
+            assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
+            assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
+        }
+    }
+
+    @Test
+    public void testCalculateInsets_navRightStatusTop() throws Exception {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+            mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+            mState.getSource(TYPE_TOP_BAR).setVisible(true);
+            mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+            mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+            WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+                    DisplayCutout.NO_CUTOUT, null, null, 0, null);
+            assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+            assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+            assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+        }
+    }
+
+    @Test
+    public void testCalculateInsets_imeIgnoredWithoutAdjustResize() {
         mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
         mState.getSource(TYPE_TOP_BAR).setVisible(true);
         mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
         mState.getSource(TYPE_IME).setVisible(true);
-        SparseIntArray typeSideMap = new SparseIntArray();
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
-                DisplayCutout.NO_CUTOUT, null, null, typeSideMap);
-        assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
-        assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
-        assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
-        assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
-        assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
-        assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
-    }
-
-    @Test
-    public void testCalculateInsets_imeAndNav() {
-        mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
-        mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
-        mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
-        mState.getSource(TYPE_IME).setVisible(true);
-        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
-                DisplayCutout.NO_CUTOUT, null, null, null);
-        assertEquals(100, insets.getStableInsetBottom());
-        assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.all()));
-        assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
-        assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
-        assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
-        assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
-    }
-
-    @Test
-    public void testCalculateInsets_navRightStatusTop() {
-        mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
-        mState.getSource(TYPE_TOP_BAR).setVisible(true);
-        mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
-        mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
-        WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
-                DisplayCutout.NO_CUTOUT, null, null, null);
-        assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
-        assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
-        assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+                DisplayCutout.NO_CUTOUT, null, null, 0, null);
+        assertEquals(0, insets.getSystemWindowInsetBottom());
+        assertTrue(insets.isVisible(ime()));
     }
 
     @Test
@@ -106,7 +130,7 @@
         mState.getSource(TYPE_IME).setVisible(true);
         mState.removeSource(TYPE_IME);
         WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
-                DisplayCutout.NO_CUTOUT, null, null, null);
+                DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, null);
         assertEquals(0, insets.getSystemWindowInsetBottom());
     }
 
@@ -114,14 +138,14 @@
     public void testEquals_differentRect() {
         mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
         mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
-        assertNotEquals(mState, mState2);
+        assertNotEqualsAndHashCode();
     }
 
     @Test
     public void testEquals_differentSource() {
         mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
         mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        assertNotEquals(mState, mState2);
+        assertNotEqualsAndHashCode();
     }
 
     @Test
@@ -130,7 +154,7 @@
         mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
         mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
         mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
-        assertEquals(mState, mState2);
+        assertEqualsAndHashCode();
     }
 
     @Test
@@ -138,7 +162,21 @@
         mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
         mState.getSource(TYPE_IME).setVisible(true);
         mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
-        assertNotEquals(mState, mState2);
+        assertNotEqualsAndHashCode();
+    }
+
+    @Test
+    public void testEquals_differentFrame() {
+        mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+        mState.setDisplayFrame(new Rect(4, 5, 6, 7));
+        assertNotEqualsAndHashCode();
+    }
+
+    @Test
+    public void testEquals_sameFrame() {
+        mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+        mState2.setDisplayFrame(new Rect(0, 1, 2, 3));
+        assertEqualsAndHashCode();
     }
 
     @Test
@@ -148,6 +186,7 @@
         mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
         Parcel p = Parcel.obtain();
         mState.writeToParcel(p, 0 /* flags */);
+        p.setDataPosition(0);
         mState2.readFromParcel(p);
         p.recycle();
         assertEquals(mState, mState2);
@@ -161,4 +200,14 @@
         assertTrue(InsetsState.getDefaultVisibility(TYPE_SIDE_BAR_3));
         assertFalse(InsetsState.getDefaultVisibility(TYPE_IME));
     }
+
+    private void assertEqualsAndHashCode() {
+        assertEquals(mState, mState2);
+        assertEquals(mState.hashCode(), mState2.hashCode());
+    }
+
+    private void assertNotEqualsAndHashCode() {
+        assertNotEquals(mState, mState2);
+        assertNotEquals(mState.hashCode(), mState2.hashCode());
+    }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
index 08ad62a..d9dac31 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TemplateClassificationIntentFactoryTest.java
@@ -41,6 +41,7 @@
 
     private static final String TEXT = "text";
     private static final String TITLE = "Map";
+    private static final String DESCRIPTION = "Opens in Maps";
     private static final String ACTION = Intent.ACTION_VIEW;
 
     @Mock
@@ -57,19 +58,6 @@
 
     @Test
     public void create_foreignText() {
-        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
-                TITLE,
-                null,
-                ACTION,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null
-        );
-
         AnnotatorModel.ClassificationResult classificationResult =
                 new AnnotatorModel.ClassificationResult(
                         TextClassifier.TYPE_ADDRESS,
@@ -81,7 +69,7 @@
                         null,
                         null,
                         null,
-                        new RemoteActionTemplate[]{remoteActionTemplate});
+                        createRemoteActionTemplates());
 
         List<TextClassifierImpl.LabeledIntent> intents =
                 mTemplateClassificationIntentFactory.create(
@@ -106,19 +94,6 @@
 
     @Test
     public void create_notForeignText() {
-        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
-                TITLE,
-                null,
-                ACTION,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null,
-                null
-        );
-
         AnnotatorModel.ClassificationResult classificationResult =
                 new AnnotatorModel.ClassificationResult(
                         TextClassifier.TYPE_ADDRESS,
@@ -130,7 +105,7 @@
                         null,
                         null,
                         null,
-                        new RemoteActionTemplate[]{remoteActionTemplate});
+                        createRemoteActionTemplates());
 
         List<TextClassifierImpl.LabeledIntent> intents =
                 mTemplateClassificationIntentFactory.create(
@@ -147,4 +122,21 @@
         assertThat(intent.getAction()).isEqualTo(ACTION);
         assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
+
+    private static RemoteActionTemplate[] createRemoteActionTemplates() {
+        return new RemoteActionTemplate[]{
+                new RemoteActionTemplate(
+                        TITLE,
+                        DESCRIPTION,
+                        ACTION,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null,
+                        null
+                )
+        };
+    }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
index 0d364a3..a1158a7 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TemplateIntentFactoryTest.java
@@ -81,7 +81,6 @@
                 REQUEST_CODE
         );
 
-
         List<TextClassifierImpl.LabeledIntent> intents =
                 mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
 
@@ -97,14 +96,79 @@
         assertThat(intent.getFlags()).isEqualTo(FLAG);
         assertThat(intent.getCategories()).containsExactly((Object[]) CATEGORY);
         assertThat(intent.getPackage()).isNull();
-        assertThat(
-                intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
+        assertThat(intent.getStringExtra(KEY_ONE)).isEqualTo(VALUE_ONE);
         assertThat(intent.getIntExtra(KEY_TWO, 0)).isEqualTo(VALUE_TWO);
         assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
     }
 
     @Test
-    public void create_packageIsNotNull() {
+    public void normalizesScheme() {
+        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+                TITLE,
+                DESCRIPTION,
+                ACTION,
+                "HTTp://www.android.com",
+                TYPE,
+                FLAG,
+                CATEGORY,
+                /* packageName */ null,
+                NAMED_VARIANTS,
+                REQUEST_CODE
+        );
+
+        List<TextClassifierImpl.LabeledIntent> intents =
+                mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+        String data = intents.get(0).getIntent().getData().toString();
+        assertThat(data).isEqualTo("http://www.android.com");
+    }
+
+    @Test
+    public void create_minimal() {
+        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+                TITLE,
+                DESCRIPTION,
+                ACTION,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null
+        );
+
+        List<TextClassifierImpl.LabeledIntent> intents =
+                mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
+
+        assertThat(intents).hasSize(1);
+        TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
+        assertThat(labeledIntent.getTitle()).isEqualTo(TITLE);
+        assertThat(labeledIntent.getDescription()).isEqualTo(DESCRIPTION);
+        assertThat(labeledIntent.getRequestCode()).isEqualTo(
+                TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
+        Intent intent = labeledIntent.getIntent();
+        assertThat(intent.getAction()).isEqualTo(ACTION);
+        assertThat(intent.getData()).isNull();
+        assertThat(intent.getType()).isNull();
+        assertThat(intent.getFlags()).isEqualTo(0);
+        assertThat(intent.getCategories()).isNull();
+        assertThat(intent.getPackage()).isNull();
+        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
+    }
+
+    @Test
+    public void invalidTemplate_nullTemplate() {
+        RemoteActionTemplate remoteActionTemplate = null;
+
+        List<TextClassifierImpl.LabeledIntent> intents =
+                mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+        assertThat(intents).isEmpty();
+    }
+
+    @Test
+    public void invalidTemplate_nonEmptyPackageName() {
         RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
                 TITLE,
                 DESCRIPTION,
@@ -121,41 +185,69 @@
         List<TextClassifierImpl.LabeledIntent> intents =
                 mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
 
-        assertThat(intents).hasSize(0);
+        assertThat(intents).isEmpty();
     }
 
     @Test
-    public void create_minimal() {
+    public void invalidTemplate_emptyTitle() {
         RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
                 null,
+                DESCRIPTION,
+                ACTION,
                 null,
                 null,
                 null,
                 null,
                 null,
                 null,
+                null
+        );
+
+        List<TextClassifierImpl.LabeledIntent> intents =
+                mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+        assertThat(intents).isEmpty();
+    }
+
+    @Test
+    public void invalidTemplate_emptyDescription() {
+        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+                TITLE,
+                null,
+                ACTION,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null
+        );
+
+        List<TextClassifierImpl.LabeledIntent> intents =
+                mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
+
+        assertThat(intents).isEmpty();
+    }
+
+    @Test
+    public void invalidTemplate_emptyIntentAction() {
+        RemoteActionTemplate remoteActionTemplate = new RemoteActionTemplate(
+                TITLE,
+                DESCRIPTION,
+                null,
+                null,
+                null,
+                null,
+                null,
                 null,
                 null,
                 null
         );
 
         List<TextClassifierImpl.LabeledIntent> intents =
-                mTemplateIntentFactory.create(new RemoteActionTemplate[]{remoteActionTemplate});
+                mTemplateIntentFactory.create(new RemoteActionTemplate[] {remoteActionTemplate});
 
-
-        assertThat(intents).hasSize(1);
-        TextClassifierImpl.LabeledIntent labeledIntent = intents.get(0);
-        assertThat(labeledIntent.getTitle()).isNull();
-        assertThat(labeledIntent.getDescription()).isNull();
-        assertThat(labeledIntent.getRequestCode()).isEqualTo(
-                TextClassifierImpl.LabeledIntent.DEFAULT_REQUEST_CODE);
-        Intent intent = labeledIntent.getIntent();
-        assertThat(intent.getAction()).isNull();
-        assertThat(intent.getData()).isNull();
-        assertThat(intent.getType()).isNull();
-        assertThat(intent.getFlags()).isEqualTo(0);
-        assertThat(intent.getCategories()).isNull();
-        assertThat(intent.getPackage()).isNull();
-        assertThat(intent.hasExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER)).isTrue();
+        assertThat(intents).isEmpty();
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 582be9d..bdd0370 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -176,6 +176,7 @@
 
         TextClassification classification = mClassifier.classifyText(request);
         assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+        assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
     }
 
     @Test
@@ -207,6 +208,7 @@
 
         TextClassification classification = mClassifier.classifyText(request);
         assertThat(classification, isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+        assertThat(classification, containsIntentWithAction(Intent.ACTION_VIEW));
     }
 
     @Test
@@ -517,6 +519,24 @@
         };
     }
 
+    private static Matcher<TextClassification> containsIntentWithAction(final String action) {
+        return new BaseMatcher<TextClassification>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof TextClassification) {
+                    TextClassification result = (TextClassification) o;
+                    return ExtrasUtils.findAction(result, action) != null;
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("intent action=").appendValue(action);
+            }
+        };
+    }
+
     private static Matcher<TextLanguage> isTextLanguage(final String languageTag) {
         return new BaseMatcher<TextLanguage>() {
             @Override
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 73af567..1980a60 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -91,8 +91,8 @@
                 .isEqualTo(ConversationAction.TYPE_CALL_PHONE);
         assertThat((float) logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_SCORE))
                 .isWithin(0.00001f).of(0.5f);
-        assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME))
-                .isEqualTo(EVENT_TIME);
+        // Never write event time.
+        assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_EVENT_TIME)).isNull();
         assertThat(logMaker.getPackageName()).isEqualTo(PACKAGE_NAME);
         assertThat(logMaker.getTaggedData(FIELD_TEXT_CLASSIFIER_WIDGET_TYPE))
                 .isEqualTo(WIDGET_TYPE);
diff --git a/graphics/java/android/graphics/Insets.aidl b/graphics/java/android/graphics/Insets.aidl
new file mode 100644
index 0000000..e65e72d
--- /dev/null
+++ b/graphics/java/android/graphics/Insets.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/graphics/Insets.aidl
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.graphics;
+
+parcelable Insets;
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index 8258b57..c64c789 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An Insets instance holds four integer offsets which describe changes to the four
@@ -27,7 +29,7 @@
  * Insets are immutable so may be treated as values.
  *
  */
-public final class Insets {
+public final class Insets implements Parcelable {
     public static final Insets NONE = new Insets(0, 0, 0, 0);
 
     public final int left;
@@ -73,7 +75,7 @@
     }
 
     /**
-     * Returns a Rect intance with the appropriate values.
+     * Returns a Rect instance with the appropriate values.
      *
      * @hide
      */
@@ -168,4 +170,29 @@
                 ", bottom=" + bottom +
                 '}';
     }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(left);
+        out.writeInt(top);
+        out.writeInt(right);
+        out.writeInt(bottom);
+    }
+
+    public static final Parcelable.Creator<Insets> CREATOR = new Parcelable.Creator<Insets>() {
+        @Override
+        public Insets createFromParcel(Parcel in) {
+            return new Insets(in.readInt(), in.readInt(), in.readInt(), in.readInt());
+        }
+
+        @Override
+        public Insets[] newArray(int size) {
+            return new Insets[size];
+        }
+    };
 }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 73442db..e617c42 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1279,7 +1279,6 @@
      * (content of the render target).
      * <p />
      * Pass null to clear any previous blend mode.
-     * As a convenience, the parameter passed is also returned.
      * <p />
      *
      * @see BlendMode
diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
index c0c6a4f..5181d89 100644
--- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
@@ -157,28 +157,22 @@
 
     @Override
     public void invalidateDrawable(Drawable who) {
-        final Callback callback = getCallback();
-
-        if (callback != null) {
-            callback.invalidateDrawable(who);
+        if (who == mColorDrawable && getCallback() != null) {
+            getCallback().invalidateDrawable(this);
         }
     }
 
     @Override
     public void scheduleDrawable(Drawable who, Runnable what, long when) {
-        final Callback callback = getCallback();
-
-        if (callback != null) {
-            callback.scheduleDrawable(who, what, when);
+        if (who == mColorDrawable && getCallback() != null) {
+            getCallback().scheduleDrawable(this, what, when);
         }
     }
 
     @Override
     public void unscheduleDrawable(Drawable who, Runnable what) {
-        final Callback callback = getCallback();
-
-        if (callback != null) {
-            callback.unscheduleDrawable(who, what);
+        if (who == mColorDrawable && getCallback() != null) {
+            getCallback().unscheduleDrawable(this, what);
         }
     }
 
diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp
index 0619a9c..905e303 100644
--- a/libs/incident/Android.bp
+++ b/libs/incident/Android.bp
@@ -36,7 +36,6 @@
 
     srcs: [
         ":libincident_aidl",
-        "proto/android/os/header.proto",
         "proto/android/os/metadata.proto",
         "src/IncidentReportArgs.cpp",
     ],
@@ -47,4 +46,4 @@
     },
 
     export_include_dirs: ["include"],
-}
+}
\ No newline at end of file
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index ee1e33c..5e8eac1 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -24,8 +24,6 @@
 #include <set>
 #include <vector>
 
-#include "frameworks/base/libs/incident/proto/android/os/header.pb.h"
-
 namespace android {
 namespace os {
 
@@ -49,7 +47,7 @@
     void setAll(bool all);
     void setDest(int dest);
     void addSection(int section);
-    void addHeader(const IncidentHeaderProto& headerProto);
+    void addHeader(const vector<uint8_t>& headerProto);
 
     inline bool all() const { return mAll; }
     bool containsSection(int section) const;
diff --git a/libs/incident/src/IncidentReportArgs.cpp b/libs/incident/src/IncidentReportArgs.cpp
index 26261ef..06b7a5b 100644
--- a/libs/incident/src/IncidentReportArgs.cpp
+++ b/libs/incident/src/IncidentReportArgs.cpp
@@ -161,15 +161,9 @@
 }
 
 void
-IncidentReportArgs::addHeader(const IncidentHeaderProto& headerProto)
+IncidentReportArgs::addHeader(const vector<uint8_t>& headerProto)
 {
-    vector<uint8_t> header;
-    auto serialized = headerProto.SerializeAsString();
-    if (serialized.empty()) return;
-    for (auto it = serialized.begin(); it != serialized.end(); it++) {
-        header.push_back((uint8_t)*it);
-    }
-    mHeaders.push_back(header);
+    mHeaders.push_back(headerProto);
 }
 
 bool
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 751d57b..4bc3897 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1614,29 +1614,59 @@
         }
 
         /**
-         * Video performance points are a set of standard performance points defined by pixel rate.
+         * Video performance points are a set of standard performance points defined by number of
+         * pixels, pixel rate and frame rate. Performance point represents an upper bound. This
+         * means that it covers all performance points with fewer pixels, pixel rate and frame
+         * rate.
          */
         public static final class PerformancePoint {
             /**
-             * Frame width in pixels.
+             * (Maximum) number of macroblocks in the frame.
+             *
+             * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks.
+             * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance
+             * is characterized using such blocks.
              */
-            public final int width;
+            public final int macroBlocks;
 
             /**
-             * Frame height in pixels.
-             */
-            public final int height;
-
-            /**
-             * Frame rate in frames per second.
+             * (Maximum) frame rate in frames per second.
              */
             public final int frameRate;
 
+            /**
+             * (Maximum) number of macroblocks processed per second.
+             */
+            public final long macroBlockRate;
+
             /* package private */
-            PerformancePoint(int width_, int height_, int frameRate_) {
-                width = width_;
-                height = height_;
-                frameRate = frameRate_;
+            PerformancePoint(int width_, int height_, int frameRate_, int maxFrameRate_) {
+                macroBlocks = saturateLongToInt(
+                        ((Math.max(1, (long)width_) + 15) / 16)
+                                * ((Math.max(1, (long)height_) + 15) / 16));
+                frameRate = Math.max(1, frameRate_);
+                macroBlockRate = Math.max(maxFrameRate_, frameRate) * macroBlocks;
+            }
+
+            /**
+             * Create a performance point for a given frame size and frame rate.
+             *
+             * @param width_ width of the frame in pixels
+             * @param height_ height of the frame in pixels
+             * @param frameRate_ frame rate in frames per second
+             */
+            public PerformancePoint(int width_, int height_, int frameRate_) {
+                this(width_, height_, frameRate_, frameRate_ /* maxFrameRate */);
+            }
+
+            private int saturateLongToInt(long value) {
+                if (value < Integer.MIN_VALUE) {
+                    return Integer.MIN_VALUE;
+                } else if (value > Integer.MAX_VALUE) {
+                    return Integer.MAX_VALUE;
+                } else {
+                    return (int)value;
+                }
             }
 
             /**
@@ -1647,26 +1677,40 @@
              * @return {@code true} if the performance point covers the format.
              */
             public boolean covers(@NonNull MediaFormat format) {
-                // for simplicity, this code assumes a 16x16 block size.
-                long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16);
-                long mbps = macroBlocks * frameRate;
-
-                long formatMacroBlocks =
-                    (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16)
-                            * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16);
-                double formatMbps =
-                    Math.ceil(formatMacroBlocks
-                              * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue());
-                return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks
-                        && formatMbps <= mbps;
+                PerformancePoint other = new PerformancePoint(
+                        format.getInteger(MediaFormat.KEY_WIDTH, 0),
+                        format.getInteger(MediaFormat.KEY_HEIGHT, 0),
+                        // safely convert ceil(double) to int through float case and Math.round
+                        Math.round((float)(
+                                Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0)
+                                        .doubleValue()))));
+                return covers(other);
             }
 
+            /**
+             * Checks whether the performance point covers another performance point. Use this
+             * method to determine if a performance point advertised by a codec covers the
+             * performance point required. This method can also be used for lose ordering as this
+             * method is transitive.
+             *
+             * @param other other performance point considered
+             *
+             * @return {@code true} if the performance point covers the other.
+             */
+            public boolean covers(@NonNull PerformancePoint other) {
+                return (macroBlocks >= other.macroBlocks
+                        && frameRate >= other.frameRate
+                        && macroBlockRate >= other.macroBlockRate);
+            }
+
+
             @Override
             public boolean equals(Object o) {
                 if (o instanceof PerformancePoint) {
                     PerformancePoint other = (PerformancePoint)o;
-                    return ((long)width * height) == ((long)other.width * other.height)
-                            && frameRate == other.frameRate;
+                    return (macroBlocks == other.macroBlocks
+                            && frameRate == other.frameRate
+                            && macroBlockRate == other.macroBlockRate);
                 }
                 return false;
             }
@@ -1931,7 +1975,8 @@
                     continue;
                 }
                 ret.add(new PerformancePoint(
-                        size.getWidth(), size.getHeight(), range.getLower().intValue()));
+                        size.getWidth(), size.getHeight(), range.getLower().intValue(),
+                        range.getUpper().intValue()));
             }
             // check if the component specified no performance point indication
             if (ret.size() == 0) {
@@ -1939,9 +1984,12 @@
             }
 
             // sort reversed by area first, then by frame rate
-            ret.sort((a, b) -> (a.width * a.height != b.width * b.height ?
-                                    (b.width * b.height - a.width * a.height) :
-                                    (b.frameRate - a.frameRate)));
+            ret.sort((a, b) -> -((a.macroBlocks != b.macroBlocks) ?
+                                        (a.macroBlocks < b.macroBlocks ? -1 : 1) :
+                                (a.macroBlockRate != b.macroBlockRate) ?
+                                        (a.macroBlockRate < b.macroBlockRate ? -1 : 1) :
+                                (a.frameRate != b.frameRate) ?
+                                        (a.frameRate < b.frameRate ? -1 : 1) : 0));
             return ret;
         }
 
@@ -2363,39 +2411,45 @@
                     boolean supported = true;
                     switch (profileLevel.level) {
                         case CodecProfileLevel.AVCLevel1:
-                            MBPS =    1485; FS =    99; BR =     64; DPB =    396; break;
+                            MBPS =     1485; FS =     99; BR =     64; DPB =    396; break;
                         case CodecProfileLevel.AVCLevel1b:
-                            MBPS =    1485; FS =    99; BR =    128; DPB =    396; break;
+                            MBPS =     1485; FS =     99; BR =    128; DPB =    396; break;
                         case CodecProfileLevel.AVCLevel11:
-                            MBPS =    3000; FS =   396; BR =    192; DPB =    900; break;
+                            MBPS =     3000; FS =    396; BR =    192; DPB =    900; break;
                         case CodecProfileLevel.AVCLevel12:
-                            MBPS =    6000; FS =   396; BR =    384; DPB =   2376; break;
+                            MBPS =     6000; FS =    396; BR =    384; DPB =   2376; break;
                         case CodecProfileLevel.AVCLevel13:
-                            MBPS =   11880; FS =   396; BR =    768; DPB =   2376; break;
+                            MBPS =    11880; FS =    396; BR =    768; DPB =   2376; break;
                         case CodecProfileLevel.AVCLevel2:
-                            MBPS =   11880; FS =   396; BR =   2000; DPB =   2376; break;
+                            MBPS =    11880; FS =    396; BR =   2000; DPB =   2376; break;
                         case CodecProfileLevel.AVCLevel21:
-                            MBPS =   19800; FS =   792; BR =   4000; DPB =   4752; break;
+                            MBPS =    19800; FS =    792; BR =   4000; DPB =   4752; break;
                         case CodecProfileLevel.AVCLevel22:
-                            MBPS =   20250; FS =  1620; BR =   4000; DPB =   8100; break;
+                            MBPS =    20250; FS =   1620; BR =   4000; DPB =   8100; break;
                         case CodecProfileLevel.AVCLevel3:
-                            MBPS =   40500; FS =  1620; BR =  10000; DPB =   8100; break;
+                            MBPS =    40500; FS =   1620; BR =  10000; DPB =   8100; break;
                         case CodecProfileLevel.AVCLevel31:
-                            MBPS =  108000; FS =  3600; BR =  14000; DPB =  18000; break;
+                            MBPS =   108000; FS =   3600; BR =  14000; DPB =  18000; break;
                         case CodecProfileLevel.AVCLevel32:
-                            MBPS =  216000; FS =  5120; BR =  20000; DPB =  20480; break;
+                            MBPS =   216000; FS =   5120; BR =  20000; DPB =  20480; break;
                         case CodecProfileLevel.AVCLevel4:
-                            MBPS =  245760; FS =  8192; BR =  20000; DPB =  32768; break;
+                            MBPS =   245760; FS =   8192; BR =  20000; DPB =  32768; break;
                         case CodecProfileLevel.AVCLevel41:
-                            MBPS =  245760; FS =  8192; BR =  50000; DPB =  32768; break;
+                            MBPS =   245760; FS =   8192; BR =  50000; DPB =  32768; break;
                         case CodecProfileLevel.AVCLevel42:
-                            MBPS =  522240; FS =  8704; BR =  50000; DPB =  34816; break;
+                            MBPS =   522240; FS =   8704; BR =  50000; DPB =  34816; break;
                         case CodecProfileLevel.AVCLevel5:
-                            MBPS =  589824; FS = 22080; BR = 135000; DPB = 110400; break;
+                            MBPS =   589824; FS =  22080; BR = 135000; DPB = 110400; break;
                         case CodecProfileLevel.AVCLevel51:
-                            MBPS =  983040; FS = 36864; BR = 240000; DPB = 184320; break;
+                            MBPS =   983040; FS =  36864; BR = 240000; DPB = 184320; break;
                         case CodecProfileLevel.AVCLevel52:
-                            MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
+                            MBPS =  2073600; FS =  36864; BR = 240000; DPB = 184320; break;
+                        case CodecProfileLevel.AVCLevel6:
+                            MBPS =  4177920; FS = 139264; BR = 240000; DPB = 696320; break;
+                        case CodecProfileLevel.AVCLevel61:
+                            MBPS =  8355840; FS = 139264; BR = 480000; DPB = 696320; break;
+                        case CodecProfileLevel.AVCLevel62:
+                            MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break;
                         default:
                             Log.w(TAG, "Unrecognized level "
                                     + profileLevel.level + " for " + mime);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index a76cf1f..12e02e7 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1520,6 +1520,7 @@
      * Create a copy of a media format object.
      */
     public MediaFormat(@NonNull MediaFormat other) {
+        this();
         mMap.putAll(other.mMap);
     }
 
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index dbeee1c..26ea6ab 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -220,4 +220,7 @@
 
     <!-- Default for Settings.Secure.CHARGING_SOUNDS_ENABLED -->
     <bool name="def_charging_sounds_enabled">true</bool>
+
+    <!-- Default for Settings.Secure.NOTIFICATION_BUBBLES -->
+    <bool name="def_notification_bubbles">true</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 23e5f0e..a7ad223 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3232,7 +3232,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 173;
+            private static final int SETTINGS_VERSION = 174;
 
             private final int mUserId;
 
@@ -4252,6 +4252,24 @@
                     currentVersion = 173;
                 }
 
+                if (currentVersion == 173) {
+                    // Version 173: Set the default value for Secure Settings: NOTIFICATION_BUBBLES
+
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+                    final Setting bubblesSetting = secureSettings.getSettingLocked(
+                            Secure.NOTIFICATION_BUBBLES);
+
+                    if (bubblesSetting.isNull()) {
+                        secureSettings.insertSettingLocked(Secure.NOTIFICATION_BUBBLES,
+                                getContext().getResources().getBoolean(
+                                        R.bool.def_notification_bubbles) ? "1" : "0", null,
+                                true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 174;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
new file mode 100644
index 0000000..3ee69b4
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins.statusbar;
+
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+
+
+/**
+ * Sends updates to {@link StateListener}s about changes to the status bar state and dozing state
+ */
+@ProvidesInterface(version = StatusBarStateController.VERSION)
+@DependsOn(target = StatusBarStateController.StateListener.class)
+public interface StatusBarStateController {
+    int VERSION = 1;
+
+    /**
+     * Current status bar state
+     */
+    int getState();
+
+    /**
+     * Is device dozing
+     */
+    boolean isDozing();
+
+    /**
+     * Adds a state listener
+     */
+    void addCallback(StateListener listener);
+
+    /**
+     * Removes callback from listeners
+     */
+    void removeCallback(StateListener listener);
+
+    /**
+     * Get amount of doze
+     */
+    float getDozeAmount();
+
+    /**
+     * Listener for StatusBarState updates
+     */
+    @ProvidesInterface(version = StateListener.VERSION)
+    public interface StateListener {
+        int VERSION = 1;
+
+        /**
+         * Callback before the new state is applied, for those who need to preempt the change.
+         */
+        default void onStatePreChange(int oldState, int newState) {
+        }
+
+        /**
+         * Callback after all listeners have had a chance to update based on the state change
+         */
+        default void onStatePostChange() {
+        }
+
+        /**
+         * Required callback. Get the new state and do what you will with it. Keep in mind that
+         * other listeners are typically unordered and don't rely on your work being done before
+         * other peers.
+         *
+         * Only called if the state is actually different.
+         */
+        default void onStateChanged(int newState) {
+        }
+
+        /**
+         * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+         */
+        default void onDozingChanged(boolean isDozing) {}
+
+        /**
+         * Callback to be notified when the doze amount changes. Useful for animations.
+         * Note: this will be called for each animation frame. Please be careful to avoid
+         * performance regressions.
+         */
+        default void onDozeAmountChanged(float linear, float eased) {}
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
new file mode 100644
index 0000000..f7ccb81
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system;
+
+import android.os.Looper;
+import android.util.Pair;
+import android.view.BatchedInputEventReceiver;
+import android.view.Choreographer;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventSender;
+
+/**
+ * @see android.view.InputChannel
+ */
+public class InputChannelCompat {
+
+    /**
+     * Callback for receiving event callbacks
+     */
+    public interface InputEventListener {
+        /**
+         * @param ev event to be handled
+         */
+        void onInputEvent(InputEvent ev);
+    }
+
+    /**
+     * Creates a dispatcher and receiver pair to better handle events across threads.
+     */
+    public static Pair<InputEventDispatcher, InputEventReceiver> createPair(String name,
+            Looper looper, Choreographer choreographer, InputEventListener listener) {
+        InputChannel[] channels = InputChannel.openInputChannelPair(name);
+
+        InputEventDispatcher dispatcher = new InputEventDispatcher(channels[0], looper);
+        InputEventReceiver receiver = new InputEventReceiver(channels[1], looper, choreographer,
+                listener);
+        return Pair.create(dispatcher, receiver);
+    }
+
+    /**
+     * @see BatchedInputEventReceiver
+     */
+    public static class InputEventReceiver {
+
+        private final BatchedInputEventReceiver mReceiver;
+        private final InputChannel mInputChannel;
+
+        public InputEventReceiver(InputChannel inputChannel, Looper looper,
+                Choreographer choreographer, final InputEventListener listener) {
+            mInputChannel = inputChannel;
+            mReceiver = new BatchedInputEventReceiver(inputChannel, looper, choreographer) {
+
+                @Override
+                public void onInputEvent(InputEvent event) {
+                    listener.onInputEvent(event);
+                    finishInputEvent(event, true /* handled */);
+                }
+            };
+        }
+
+        /**
+         * @see BatchedInputEventReceiver#dispose()
+         */
+        public void dispose() {
+            mReceiver.dispose();
+            mInputChannel.dispose();
+        }
+    }
+
+    /**
+     * @see InputEventSender
+     */
+    public static class InputEventDispatcher {
+
+        private final InputChannel mInputChannel;
+        private final InputEventSender mSender;
+
+        private InputEventDispatcher(InputChannel inputChannel, Looper looper) {
+            mInputChannel = inputChannel;
+            mSender = new InputEventSender(inputChannel, looper) { };
+        }
+
+        /**
+         * @see InputEventSender#sendInputEvent(int, InputEvent)
+         */
+        public void dispatch(InputEvent ev) {
+            mSender.sendInputEvent(ev.getSequenceNumber(), ev);
+        }
+
+        /**
+         * @see InputEventSender#dispose()
+         */
+        public void dispose() {
+            mSender.dispose();
+            mInputChannel.dispose();
+        }
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 2bdbf0b..221782e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -20,6 +20,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
 
 /**
  * @see RemoteAnimationTarget
@@ -47,6 +48,8 @@
     public final boolean isNotInRecents;
     public final Rect contentInsets;
 
+    private final SurfaceControl mStartLeash;
+
     public RemoteAnimationTargetCompat(RemoteAnimationTarget app) {
         taskId = app.taskId;
         mode = app.mode;
@@ -59,6 +62,8 @@
         isNotInRecents = app.isNotInRecents;
         contentInsets = app.contentInsets;
         activityType = app.windowConfiguration.getActivityType();
+
+        mStartLeash = app.startLeash;
     }
 
     public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
@@ -69,4 +74,14 @@
         }
         return appsCompat;
     }
+
+    /**
+     * @see SurfaceControl#release()
+     */
+    public void release() {
+        leash.mSurfaceControl.release();
+        if (mStartLeash != null) {
+            mStartLeash.release();
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index d5bd2b2..1539582 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -299,8 +299,9 @@
                 displayText.toString().split(mSeparator.toString()),
                 anySimReadyAndInService && !missingSimsWithSubs,
                 subsIds);
-        if (mCarrierTextCallback != null) {
-            handler.post(() -> mCarrierTextCallback.updateCarrierInfo(info));
+        final CarrierTextCallback callback = mCarrierTextCallback;
+        if (callback != null) {
+            handler.post(() -> callback.updateCarrierInfo(info));
         }
 
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 7218acf..6c970c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -15,8 +15,8 @@
 import com.android.keyguard.clock.ClockManager;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 
 import java.util.TimeZone;
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index c3f61ee..5672073 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.privacy.PrivacyItemController;
@@ -55,7 +56,6 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.SmartReplyController;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 9b3d7ed..755d6fc 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -33,6 +33,7 @@
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.power.EnhancedEstimates;
 import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -40,7 +41,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -152,6 +153,15 @@
         return new VolumeDialogComponent(systemUi, context);
     }
 
+    /**
+     * Provides status bar state controller implementation
+     */
+    @Singleton
+    @Provides
+    public StatusBarStateController provideStatusBarStateController(Context context) {
+        return new StatusBarStateControllerImpl();
+    }
+
     @Singleton
     @Provides
     public NotificationData.KeyguardEnvironment provideKeyguardEnvironment(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 6877f5e..41bc1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -28,6 +28,9 @@
 import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
 
 import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.app.IActivityTaskManager;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.PendingIntent;
@@ -35,11 +38,13 @@
 import android.content.pm.ActivityInfo;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.util.StatsLog;
+import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -51,7 +56,9 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -60,6 +67,7 @@
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -93,6 +101,8 @@
 
     private final Context mContext;
     private final NotificationEntryManager mNotificationEntryManager;
+    private final IActivityTaskManager mActivityTaskManager;
+    private final BubbleTaskStackListener mTaskStackListener;
     private BubbleStateChangeListener mStateChangeListener;
     private BubbleExpandListener mExpandListener;
     private LayoutInflater mInflater;
@@ -176,6 +186,10 @@
         mStatusBarWindowController = statusBarWindowController;
         mStatusBarStateListener = new StatusBarStateListener();
         Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
+
+        mActivityTaskManager = ActivityTaskManager.getService();
+        mTaskStackListener = new BubbleTaskStackListener();
+        ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
     }
 
     /**
@@ -533,6 +547,64 @@
                 || autoBubbleAll;
     }
 
+    /**
+     * This task stack listener is responsible for responding to tasks moved to the front
+     * which are on the default (main) display. When this happens, expanded bubbles must be
+     * collapsed so the user may interact with the app which was just moved to the front.
+     * <p>
+     * This listener is registered with SystemUI's ActivityManagerWrapper which dispatches
+     * these calls via a main thread Handler.
+     */
+    @MainThread
+    private class BubbleTaskStackListener extends TaskStackChangeListener {
+
+        @Nullable
+        private ActivityManager.StackInfo findStackInfo(int taskId) throws RemoteException {
+            final List<ActivityManager.StackInfo> stackInfoList =
+                    mActivityTaskManager.getAllStackInfos();
+            // Iterate through stacks from top to bottom.
+            final int stackCount = stackInfoList.size();
+            for (int stackIndex = 0; stackIndex < stackCount; stackIndex++) {
+                final ActivityManager.StackInfo stackInfo = stackInfoList.get(stackIndex);
+                // Iterate through tasks from top to bottom.
+                for (int taskIndex = stackInfo.taskIds.length - 1; taskIndex >= 0; taskIndex--) {
+                    if (stackInfo.taskIds[taskIndex] == taskId) {
+                        return stackInfo;
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public void onTaskMovedToFront(int taskId) {
+            ActivityManager.StackInfo stackInfo = null;
+            try {
+                stackInfo = findStackInfo(taskId);
+            } catch (RemoteException e) {
+                e.rethrowAsRuntimeException();
+            }
+            if (stackInfo != null && stackInfo.displayId == Display.DEFAULT_DISPLAY
+                    && mStackView != null) {
+                mStackView.collapseStack();
+            }
+        }
+
+        /**
+         * This is a workaround for the case when the activity had to be created in a new task.
+         * Existing code in ActivityStackSupervisor checks the display where the activity
+         * ultimately ended up, displays an error message toast, and calls this method instead of
+         * onTaskMovedToFront.
+         */
+        // TODO(b/124058588): add requestedDisplayId to this callback, ignore unless matches
+        @Override
+        public void onActivityLaunchOnSecondaryDisplayFailed() {
+            if (mStackView != null) {
+                mStackView.collapseStack();
+            }
+        }
+    }
+
     private static boolean shouldAutoBubbleMessages(Context context) {
         return Settings.Secure.getInt(context.getContentResolver(),
                 ENABLE_AUTO_BUBBLE_MESSAGES, 0) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 305f866..f6f3fa6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -41,6 +41,7 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
+import androidx.annotation.MainThread;
 import androidx.annotation.Nullable;
 import androidx.dynamicanimation.animation.DynamicAnimation;
 import androidx.dynamicanimation.animation.SpringAnimation;
@@ -384,7 +385,10 @@
 
     /**
      * Collapses the stack of bubbles.
+     * <p>
+     * Must be called from the main thread.
      */
+    @MainThread
     public void collapseStack() {
         if (mIsExpanded) {
             // TODO: Save opened bubble & move it to top of stack
@@ -402,7 +406,10 @@
 
     /**
      * Expands the stack fo bubbles.
+     * <p>
+     * Must be called from the main thread.
      */
+    @MainThread
     public void expandStack() {
         if (!mIsExpanded) {
             mExpandedBubble = getTopBubble();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 2c23c0c..74ddc8f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -22,6 +22,8 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.graphics.Color;
+import android.graphics.Insets;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -32,6 +34,7 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -266,6 +269,24 @@
                     }
                 }
             });
+            mActivityView.setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
+                ActivityView activityView = (ActivityView) view;
+                // Here we assume that the position of the ActivityView on the screen
+                // remains regardless of IME status. When we move ActivityView, the
+                // forwardedInsets should be computed not against the current location
+                // and size, but against the post-moved location and size.
+                Point displaySize = new Point();
+                view.getContext().getDisplay().getSize(displaySize);
+                int[] windowLocation = view.getLocationOnScreen();
+                final int windowBottom = windowLocation[1] + view.getHeight();
+                final int keyboardHeight = insets.getSystemWindowInsetBottom()
+                        - insets.getStableInsetBottom();
+                final int insetsBottom = Math.max(0,
+                        windowBottom + keyboardHeight - displaySize.y);
+                activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
+                return view.onApplyWindowInsets(insets);
+            });
+
         }
         return mActivityView;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 4ff27b1..8f215ff 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -35,9 +35,9 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.util.AsyncSensorManager;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index c4c8bc7..684175c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -51,8 +51,8 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
 import com.android.systemui.statusbar.policy.ZenModeController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index e1a4378..e275690 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -58,10 +58,10 @@
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.PagedTileLayout.TilePage;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QuickStatusBarHeader;
-import com.android.systemui.statusbar.StatusBarStateController;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 2811505..be749ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -47,7 +47,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 4f9d428..6a49b80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -44,8 +44,9 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 98a3a54..490317b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -47,6 +47,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 546b2e9..01b0bb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -26,7 +26,6 @@
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.MathUtils;
 import android.view.DisplayCutout;
 import android.view.View;
 import android.view.ViewGroup;
@@ -38,7 +37,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -118,8 +118,8 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        Dependency.get(StatusBarStateController.class)
-                .addCallback(this, StatusBarStateController.RANK_SHELF);
+        ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+                .addCallback(this, SysuiStatusBarStateController.RANK_SHELF);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index f2ff85b..662cf51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -61,7 +61,7 @@
     protected final NotificationLockscreenUserManager mLockscreenUserManager;
     protected final NotificationGroupManager mGroupManager;
     protected final VisualStabilityManager mVisualStabilityManager;
-    private final StatusBarStateController mStatusBarStateController;
+    private final StatusBarStateControllerImpl mStatusBarStateController;
     private final NotificationEntryManager mEntryManager;
 
     // Lazy
@@ -82,7 +82,7 @@
             NotificationLockscreenUserManager notificationLockscreenUserManager,
             NotificationGroupManager groupManager,
             VisualStabilityManager visualStabilityManager,
-            StatusBarStateController statusBarStateController,
+            StatusBarStateControllerImpl statusBarStateController,
             NotificationEntryManager notificationEntryManager,
             Lazy<ShadeController> shadeController) {
         mLockscreenUserManager = notificationLockscreenUserManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
similarity index 60%
rename from packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 54bce1c..ad5aa57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -11,27 +11,22 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
 package com.android.systemui.statusbar;
 
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
-import android.annotation.IntDef;
 import android.util.FloatProperty;
 import android.view.animation.Interpolator;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.CallbackController;
 
-import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.Comparator;
 
@@ -42,24 +37,25 @@
  * Tracks and reports on {@link StatusBarState}.
  */
 @Singleton
-public class StatusBarStateController implements CallbackController<StateListener> {
+public class StatusBarStateControllerImpl implements SysuiStatusBarStateController,
+        CallbackController<StateListener> {
     private static final String TAG = "SbStateController";
 
     private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
     private static final int MIN_STATE = StatusBarState.SHADE;
 
-    private static final Comparator <RankedListener> mComparator
-            = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
-    private static final FloatProperty<StatusBarStateController> SET_DARK_AMOUNT_PROPERTY =
-            new FloatProperty<StatusBarStateController>("mDozeAmount") {
+    private static final Comparator<RankedListener> sComparator =
+            Comparator.comparingInt(o -> o.mRank);
+    private static final FloatProperty<StatusBarStateControllerImpl> SET_DARK_AMOUNT_PROPERTY =
+            new FloatProperty<StatusBarStateControllerImpl>("mDozeAmount") {
 
                 @Override
-                public void setValue(StatusBarStateController object, float value) {
+                public void setValue(StatusBarStateControllerImpl object, float value) {
                     object.setDozeAmountInternal(value);
                 }
 
                 @Override
-                public Float get(StatusBarStateController object) {
+                public Float get(StatusBarStateControllerImpl object) {
                     return object.mDozeAmount;
                 }
             };
@@ -95,29 +91,16 @@
      */
     private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
 
-    // TODO: b/115739177 (remove this explicit ordering if we can)
-    @Retention(SOURCE)
-    @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
-    public @interface SbStateListenerRank {}
-    // This is the set of known dependencies when updating StatusBarState
-    public static final int RANK_STATUS_BAR = 0;
-    public static final int RANK_STATUS_BAR_WINDOW_CONTROLLER = 1;
-    public static final int RANK_STACK_SCROLLER = 2;
-    public static final int RANK_SHELF = 3;
-
     @Inject
-    public StatusBarStateController() {
+    public StatusBarStateControllerImpl() {
     }
 
+    @Override
     public int getState() {
         return mState;
     }
 
-    /**
-     * Update the status bar state
-     * @param state see {@link StatusBarState} for valid options
-     * @return {@code true} if the state changed, else {@code false}
-     */
+    @Override
     public boolean setState(int state) {
         if (state > MAX_STATE || state < MIN_STATE) {
             throw new IllegalArgumentException("Invalid state " + state);
@@ -127,40 +110,38 @@
         }
         synchronized (mListeners) {
             for (RankedListener rl : new ArrayList<>(mListeners)) {
-                rl.listener.onStatePreChange(mState, state);
+                rl.mListener.onStatePreChange(mState, state);
             }
             mLastState = mState;
             mState = state;
             for (RankedListener rl : new ArrayList<>(mListeners)) {
-                rl.listener.onStateChanged(mState);
+                rl.mListener.onStateChanged(mState);
             }
 
             for (RankedListener rl : new ArrayList<>(mListeners)) {
-                rl.listener.onStatePostChange();
+                rl.mListener.onStatePostChange();
             }
         }
 
         return true;
     }
 
+    @Override
     public boolean isDozing() {
         return mIsDozing;
     }
 
+    @Override
     public float getDozeAmount() {
         return mDozeAmount;
     }
 
+    @Override
     public float getInterpolatedDozeAmount() {
         return mDozeInterpolator.getInterpolation(mDozeAmount);
     }
 
-    /**
-     * Update the dozing state from {@link StatusBar}'s perspective
-     * @param isDozing well, are we dozing?
-     * @return {@code true} if the state changed, else {@code false}
-     */
-    @SuppressWarnings("UnusedReturnValue")
+    @Override
     public boolean setIsDozing(boolean isDozing) {
         if (mIsDozing == isDozing) {
             return false;
@@ -170,19 +151,14 @@
 
         synchronized (mListeners) {
             for (RankedListener rl : new ArrayList<>(mListeners)) {
-                rl.listener.onDozingChanged(isDozing);
+                rl.mListener.onDozingChanged(isDozing);
             }
         }
 
         return true;
     }
 
-    /**
-     * Changes the current doze amount.
-     *
-     * @param dozeAmount New doze/dark amount.
-     * @param animated If change should be animated or not. This will cancel current animations.
-     */
+    @Override
     public void setDozeAmount(float dozeAmount, boolean animated) {
         if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
             if (animated && mDozeAmountTarget == dozeAmount) {
@@ -217,27 +193,32 @@
         float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
         synchronized (mListeners) {
             for (RankedListener rl : new ArrayList<>(mListeners)) {
-                rl.listener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
+                rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
             }
         }
     }
 
+    @Override
     public boolean goingToFullShade() {
         return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
     }
 
+    @Override
     public void setLeaveOpenOnKeyguardHide(boolean leaveOpen) {
         mLeaveOpenOnKeyguardHide = leaveOpen;
     }
 
+    @Override
     public boolean leaveOpenOnKeyguardHide() {
         return mLeaveOpenOnKeyguardHide;
     }
 
+    @Override
     public boolean fromShadeLocked() {
         return mLastState == StatusBarState.SHADE_LOCKED;
     }
 
+    @Override
     public void addCallback(StateListener listener) {
         synchronized (mListeners) {
             addListenerInternalLocked(listener, Integer.MAX_VALUE);
@@ -254,6 +235,8 @@
      * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
      * (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
      */
+    @Deprecated
+    @Override
     public void addCallback(StateListener listener, @SbStateListenerRank int rank) {
         synchronized (mListeners) {
             addListenerInternalLocked(listener, rank);
@@ -264,91 +247,38 @@
     private void addListenerInternalLocked(StateListener listener, int rank) {
         // Protect against double-subscribe
         for (RankedListener rl : mListeners) {
-            if (rl.listener.equals(listener)) {
+            if (rl.mListener.equals(listener)) {
                 return;
             }
         }
 
-        RankedListener rl = new RankedListener(listener, rank);
+        RankedListener rl = new SysuiStatusBarStateController.RankedListener(listener, rank);
         mListeners.add(rl);
-        mListeners.sort(mComparator);
+        mListeners.sort(sComparator);
     }
 
+
+    @Override
     public void removeCallback(StateListener listener) {
         synchronized (mListeners) {
-            mListeners.removeIf((it) -> it.listener.equals(listener));
+            mListeners.removeIf((it) -> it.mListener.equals(listener));
         }
     }
 
+    @Override
     public void setKeyguardRequested(boolean keyguardRequested) {
         mKeyguardRequested = keyguardRequested;
     }
 
+    @Override
     public boolean isKeyguardRequested() {
         return mKeyguardRequested;
     }
 
+    /**
+     * Returns String readable state of status bar from {@link StatusBarState}
+     */
     public static String describe(int state) {
         return StatusBarState.toShortString(state);
     }
-
-    private class RankedListener {
-        private final StateListener listener;
-        private final int rank;
-
-        private RankedListener(StateListener l, int r) {
-            listener = l;
-            rank = r;
-        }
-    }
-
-    /**
-     * Listener for StatusBarState updates
-     */
-    public interface StateListener {
-
-        /**
-         * Callback before the new state is applied, for those who need to preempt the change.
-         *
-         * @param oldState state before the change
-         * @param newState new state to be applied in {@link #onStateChanged}
-         */
-        public default void onStatePreChange(int oldState, int newState) {
-        }
-
-        /**
-         * Callback after all listeners have had a chance to update based on the state change
-         */
-        public default void onStatePostChange() {
-        }
-
-        /**
-         * Required callback. Get the new state and do what you will with it. Keep in mind that
-         * other listeners are typically unordered and don't rely on your work being done before
-         * other peers.
-         *
-         * Only called if the state is actually different.
-         *
-         * @param newState the new {@link StatusBarState}
-         */
-        default void onStateChanged(int newState) {
-        }
-
-        /**
-         * Callback to be notified when Dozing changes. Dozing is stored separately from state.
-         *
-         * @param isDozing {@code true} if dozing according to {@link StatusBar}
-         */
-        public default void onDozingChanged(boolean isDozing) {}
-
-        /**
-         * Callback to be notified when the doze amount changes. Useful for animations.
-         * Note: this will be called for each animation frame. Please be careful to avoid
-         * performance regressions.
-         *
-         * @param linear A number from 0 to 1, where 1 means that the device is dozing.
-         * @param eased Same as {@code linear} but transformed by an interpolator.
-         */
-        default void onDozeAmountChanged(float linear, float eased) {}
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
new file mode 100644
index 0000000..dc5e1e9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Sends updates to {@link StateListener}s about changes to the status bar state and dozing state
+ */
+public interface SysuiStatusBarStateController extends StatusBarStateController {
+
+    // TODO: b/115739177 (remove this explicit ordering if we can)
+    @Retention(SOURCE)
+    @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
+    @interface SbStateListenerRank {}
+    // This is the set of known dependencies when updating StatusBarState
+    int RANK_STATUS_BAR = 0;
+    int RANK_STATUS_BAR_WINDOW_CONTROLLER = 1;
+    int RANK_STACK_SCROLLER = 2;
+    int RANK_SHELF = 3;
+
+    /**
+     * Add a listener and a rank based on the priority of this message
+     * @param listener the listener
+     * @param rank the order in which you'd like to be called. Ranked listeners will be
+     * notified before unranked, and we will sort ranked listeners from low to high
+     *
+     * @deprecated This method exists only to solve latent inter-dependencies from refactoring
+     * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
+     * (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
+     */
+    @Deprecated
+    void addCallback(StateListener listener, int rank);
+
+    /**
+     * Update the status bar state
+     * @param state see {@link StatusBarState} for valid options
+     * @return {@code true} if the state changed, else {@code false}
+     */
+    boolean setState(int state);
+
+    /**
+     * Update the dozing state from {@link StatusBar}'s perspective
+     * @param isDozing well, are we dozing?
+     * @return {@code true} if the state changed, else {@code false}
+     */
+    boolean setIsDozing(boolean isDozing);
+
+    /**
+     * Changes the current doze amount.
+     *
+     * @param dozeAmount New doze/dark amount.
+     * @param animated If change should be animated or not. This will cancel current animations.
+     */
+    void setDozeAmount(float dozeAmount, boolean animated);
+
+    /**
+     * Sets whether to leave status bar open when hiding keyguard
+     */
+    void setLeaveOpenOnKeyguardHide(boolean leaveOpen);
+
+    /**
+     * Whether to leave status bar open when hiding keyguard
+     */
+    boolean leaveOpenOnKeyguardHide();
+
+    /**
+     * Interpolated doze amount
+     */
+    float getInterpolatedDozeAmount();
+
+    /**
+     * Whether status bar is going to full shade
+     */
+    boolean goingToFullShade();
+
+    /**
+     * Whether the previous state of the status bar was the shade locked
+     */
+    boolean fromShadeLocked();
+
+    /**
+     * Set keyguard requested
+     */
+    void setKeyguardRequested(boolean keyguardRequested);
+
+    /**
+     * Is keyguard requested
+     */
+    boolean isKeyguardRequested();
+
+    /**
+     * Listener with rankings SbStateListenerRank that have dependencies so must be updated
+     * in a certain order
+     */
+    class RankedListener {
+        final StateListener mListener;
+        final int mRank;
+
+        RankedListener(StateListener l, int r) {
+            mListener = l;
+            mRank = r;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index c50f10b..7cbe1a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -35,8 +35,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 5e52419..c4ecb82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -33,9 +33,9 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.UiOffloadThread;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index aa221993..fea01ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -42,11 +42,11 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 4bdc170..4c9c2f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -17,12 +17,7 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.os.Build;
 import android.view.View;
 
 import com.android.internal.graphics.ColorUtils;
@@ -49,43 +44,22 @@
     }
 
     @Override
-    public void onReinflated() {
-        super.onReinflated();
-
-        Configuration configuration = mView.getResources().getConfiguration();
-        boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
-                == Configuration.UI_MODE_NIGHT_YES;
-
-        float[] hsl = new float[] {0f, 0f, 0f};
-        ColorUtils.colorToHSL(mBackgroundColor, hsl);
-        boolean backgroundIsDark = Color.alpha(mBackgroundColor) == 0
-                || hsl[1] == 0 && hsl[2] < 0.5;
-        boolean backgroundHasColor = hsl[1] > 0;
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        super.onContentUpdated(row);
 
         // Let's invert the notification colors when we're in night mode and
         // the notification background isn't colorized.
-        if (!backgroundIsDark && !backgroundHasColor && nightMode
-                && mRow.getEntry().targetSdk < Build.VERSION_CODES.Q) {
-            Paint paint = new Paint();
-            ColorMatrix matrix = new ColorMatrix();
-            ColorMatrix tmp = new ColorMatrix();
-            // Inversion should happen on Y'UV space to conseve the colors and
-            // only affect the luminosity.
-            matrix.setRGB2YUV();
-            tmp.set(new float[]{
-                    -1f, 0f, 0f, 0f, 255f,
-                    0f, 1f, 0f, 0f, 0f,
-                    0f, 0f, 1f, 0f, 0f,
-                    0f, 0f, 0f, 1f, 0f
-            });
-            matrix.postConcat(tmp);
-            tmp.setYUV2RGB();
-            matrix.postConcat(tmp);
-            paint.setColorFilter(new ColorMatrixColorFilter(matrix));
-            mView.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
+        if (needsInversion(mBackgroundColor, mView)) {
+            invertViewLuminosity(mView);
 
-            hsl[2] = 1f - hsl[2];
-            mBackgroundColor = ColorUtils.HSLToColor(hsl);
+            // Also invert background color if necessary
+            // (Otherwise we'd end-up with white on white.)
+            float[] hsl = new float[] {0f, 0f, 0f};
+            ColorUtils.colorToHSL(mBackgroundColor, hsl);
+            if (mBackgroundColor != Color.TRANSPARENT && hsl[2] > 0.5) {
+                hsl[2] = 1f - hsl[2];
+                mBackgroundColor = ColorUtils.HSLToColor(hsl);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
new file mode 100644
index 0000000..49a8d56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Wraps a notification containing a decorated custom view.
+ */
+public class NotificationDecoratedCustomViewWrapper extends NotificationTemplateViewWrapper {
+
+    private View mWrappedView = null;
+
+    protected NotificationDecoratedCustomViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+    }
+
+    @Override
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        ViewGroup container = mView.findViewById(
+                com.android.internal.R.id.notification_main_column);
+        Integer childIndex = (Integer) container.getTag(
+                com.android.internal.R.id.notification_custom_view_index_tag);
+        if (childIndex != null && childIndex != -1) {
+            mWrappedView = container.getChildAt(childIndex);
+        }
+        if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
+            invertViewLuminosity(mWrappedView);
+        }
+        super.onContentUpdated(row);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 9258c99..4c06ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -16,13 +16,22 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import android.annotation.ColorInt;
+import android.app.Notification;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.view.NotificationHeaderView;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
+import com.android.internal.graphics.ColorUtils;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.notification.TransformState;
@@ -50,6 +59,11 @@
             } else if ("messaging".equals(v.getTag())) {
                 return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
             }
+            Class<? extends Notification.Style> style =
+                    row.getEntry().notification.getNotification().getNotificationStyle();
+            if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
+                return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
+            }
             return new NotificationTemplateViewWrapper(ctx, v, row);
         } else if (v instanceof NotificationHeaderView) {
             return new NotificationHeaderViewWrapper(ctx, v, row);
@@ -75,14 +89,110 @@
         if (shouldClearBackgroundOnReapply()) {
             mBackgroundColor = 0;
         }
-        Drawable background = mView.getBackground();
-        if (background instanceof ColorDrawable) {
-            int backgroundColor = ((ColorDrawable) background).getColor();
-            if (backgroundColor != Color.TRANSPARENT) {
-                mBackgroundColor = backgroundColor;
-                mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+        int backgroundColor = getBackgroundColor(mView);
+        if (backgroundColor != Color.TRANSPARENT) {
+            mBackgroundColor = backgroundColor;
+            mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+        }
+    }
+
+    protected boolean needsInversion(int defaultBackgroundColor, View view) {
+        if (view == null) {
+            return false;
+        }
+
+        Configuration configuration = mView.getResources().getConfiguration();
+        boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                == Configuration.UI_MODE_NIGHT_YES;
+        if (!nightMode) {
+            return false;
+        }
+
+        int background = getBackgroundColor(view);
+        if (background == Color.TRANSPARENT) {
+            background = defaultBackgroundColor;
+        }
+        if (background == Color.TRANSPARENT) {
+            background = resolveBackgroundColor();
+        }
+
+        float[] hsl = new float[] {0f, 0f, 0f};
+        ColorUtils.colorToHSL(background, hsl);
+
+        // Notifications with colored backgrounds should not be inverted
+        if (hsl[1] != 0) {
+            return false;
+        }
+
+        // Invert white or light gray backgrounds.
+        boolean isLightGrayOrWhite = hsl[1] == 0 && hsl[2] > 0.5;
+        if (isLightGrayOrWhite) {
+            return true;
+        }
+
+        // Now let's check if there's unprotected text somewhere, and invert if we find it.
+        if (view instanceof ViewGroup) {
+            return childrenNeedInversion(background, (ViewGroup) view);
+        } else {
+            return false;
+        }
+    }
+
+    private boolean childrenNeedInversion(@ColorInt int parentBackground, ViewGroup viewGroup) {
+        if (viewGroup == null) {
+            return false;
+        }
+
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            View child = viewGroup.getChildAt(i);
+            int backgroundColor = getBackgroundColor(viewGroup);
+            if (backgroundColor == Color.TRANSPARENT) {
+                backgroundColor = parentBackground;
+            }
+            if (child instanceof TextView) {
+                int foreground = ((TextView) child).getCurrentTextColor();
+                if (ColorUtils.calculateContrast(foreground, backgroundColor) < 3) {
+                    return true;
+                }
+            } else if (child instanceof ViewGroup) {
+                if (childrenNeedInversion(backgroundColor, (ViewGroup) child)) {
+                    return true;
+                }
             }
         }
+
+        return false;
+    }
+
+    protected int getBackgroundColor(View view) {
+        if (view == null) {
+            return Color.TRANSPARENT;
+        }
+        Drawable background = view.getBackground();
+        if (background instanceof ColorDrawable) {
+            return ((ColorDrawable) background).getColor();
+        }
+        return Color.TRANSPARENT;
+    }
+
+    protected void invertViewLuminosity(View view) {
+        Paint paint = new Paint();
+        ColorMatrix matrix = new ColorMatrix();
+        ColorMatrix tmp = new ColorMatrix();
+        // Inversion should happen on Y'UV space to conserve the colors and
+        // only affect the luminosity.
+        matrix.setRGB2YUV();
+        tmp.set(new float[]{
+                -1f, 0f, 0f, 0f, 255f,
+                0f, 1f, 0f, 0f, 0f,
+                0f, 0f, 1f, 0f, 0f,
+                0f, 0f, 0f, 1f, 0f
+        });
+        matrix.postConcat(tmp);
+        tmp.setYUV2RGB();
+        matrix.postConcat(tmp);
+        paint.setColorFilter(new ColorMatrixColorFilter(matrix));
+        view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
     }
 
     protected boolean shouldClearBackgroundOnReapply() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 855cfd9..7105876 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -86,6 +86,8 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
 import com.android.systemui.statusbar.EmptyShadeView;
@@ -94,8 +96,7 @@
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.FakeShadowView;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -664,8 +665,8 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        Dependency.get(StatusBarStateController.class)
-                .addCallback(mStateListener, StatusBarStateController.RANK_STACK_SCROLLER);
+        ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+                .addCallback(mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
 
@@ -5430,7 +5431,8 @@
             mHeadsUpAppearanceController.setPublicMode(publicMode);
         }
 
-        StatusBarStateController state = Dependency.get(StatusBarStateController.class);
+        SysuiStatusBarStateController state = (SysuiStatusBarStateController)
+                Dependency.get(StatusBarStateController.class);
         setHideSensitive(publicMode, state.goingToFullShade() /* animate */);
         setDimmed(onKeyguard, state.fromShadeLocked() /* animate */);
         setExpandingEnabled(!onKeyguard);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 35763dc..6410860 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -33,8 +33,8 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
 import com.android.systemui.statusbar.policy.EncryptionHelper;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 280dda0..d9d74b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -24,8 +24,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 
 /**
  * Controller which handles all the doze animations of the scrims.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 035ccf1..4c1c0a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -38,9 +38,9 @@
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
 import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 1944c3f..5ccb9b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -33,9 +33,9 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index ee047e4..538d797 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -85,6 +85,7 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -92,7 +93,6 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.ContextualButton.ContextButtonListener;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index d364356..b613e8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -25,12 +25,12 @@
 
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
 import com.android.systemui.statusbar.InflationTask;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index bb9e418..cc8af3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -22,11 +22,11 @@
 import android.util.Log;
 
 import com.android.systemui.Dependency;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 9e99fe9..62f85fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -11,6 +11,9 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
@@ -19,10 +22,10 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -31,9 +34,6 @@
 import java.util.ArrayList;
 import java.util.function.Function;
 
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-
 /**
  * A controller for the space in the status bar to the left of the system icons. This area is
  * normally reserved for notifications.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a9727c9..069703e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -17,8 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import static com.android.systemui.SysUiServiceProvider.getComponent;
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
-        .ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -63,6 +62,8 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -73,8 +74,6 @@
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f17145d..4d0c8c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -44,9 +44,10 @@
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
@@ -142,8 +143,8 @@
     private boolean mIgnoreXTouchSlop;
     private boolean mExpandLatencyTracking;
     protected final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
-    protected final StatusBarStateController mStatusBarStateController =
-            Dependency.get(StatusBarStateController.class);
+    protected final SysuiStatusBarStateController mStatusBarStateController =
+            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
 
     protected void onExpandingFinished() {
         mBar.onExpandingFinished();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 37a0610..9f3bec6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -163,6 +163,7 @@
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.recents.Recents;
@@ -188,7 +189,8 @@
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
@@ -558,8 +560,8 @@
     };
     private boolean mNoAnimationOnNextBarModeChange;
     protected FalsingManager mFalsingManager;
-    private final StatusBarStateController
-            mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+    private final SysuiStatusBarStateController mStatusBarStateController =
+            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
 
     private final KeyguardUpdateMonitorCallback mUpdateCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -650,7 +652,8 @@
         }
 
         mColorExtractor.addOnColorsChangedListener(this);
-        mStatusBarStateController.addCallback(this, StatusBarStateController.RANK_STATUS_BAR);
+        mStatusBarStateController.addCallback(this,
+                StatusBarStateControllerImpl.RANK_STATUS_BAR);
 
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mDreamManager = IDreamManager.Stub.asInterface(
@@ -804,15 +807,17 @@
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
         mNotificationIconAreaController = SystemUIFactory.getInstance()
-                .createNotificationIconAreaController(
-                        context, this, mStatusBarStateController, mNotificationListener);
+                .createNotificationIconAreaController(context, this,
+                        mStatusBarStateController, mNotificationListener);
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelf);
 
         Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
-        // Allow plugins to reference DarkIconDispatcher
+        // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
         Dependency.get(PluginDependencyProvider.class)
                 .allowPluginDependency(DarkIconDispatcher.class);
+        Dependency.get(PluginDependencyProvider.class)
+                .allowPluginDependency(StatusBarStateController.class);
         FragmentHostManager.get(mStatusBarWindow)
                 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
                     CollapsedStatusBarFragment statusBarFragment =
@@ -3370,7 +3375,8 @@
         // ringing.
         // Other transitions are covered in handleVisibleToUserChanged().
         if (mVisible && (newState == StatusBarState.SHADE_LOCKED
-                || (Dependency.get(StatusBarStateController.class).goingToFullShade()))) {
+                || (((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+                .goingToFullShade()))) {
             clearNotificationEffects();
         }
         if (newState == StatusBarState.KEYGUARD) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index bb23608..5014783 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -42,10 +42,11 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
@@ -701,7 +702,8 @@
     }
 
     public boolean isGoingToNotificationShade() {
-        return Dependency.get(StatusBarStateController.class).leaveOpenOnKeyguardHide();
+        return ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+                .leaveOpenOnKeyguardHide();
     }
 
     public boolean isSecure(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 86326be..b0e006d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -51,13 +51,13 @@
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index df7f53b..e9705ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -48,6 +48,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -56,7 +57,7 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
@@ -92,8 +93,8 @@
             Dependency.get(NotificationViewHierarchyManager.class);
     private final NotificationLockscreenUserManager mLockscreenUserManager =
             Dependency.get(NotificationLockscreenUserManager.class);
-    private final StatusBarStateController mStatusBarStateController =
-            Dependency.get(StatusBarStateController.class);
+    private final SysuiStatusBarStateController mStatusBarStateController =
+            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
     private final NotificationEntryManager mEntryManager =
             Dependency.get(NotificationEntryManager.class);
     private final NotificationRowBinder mNotificationRowBinder =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 8d58410..21d9dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -35,13 +35,14 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -57,10 +58,10 @@
         StatusBarStateController.StateListener {
 
     private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
-    private final StatusBarStateController mStatusBarStateController
-            = Dependency.get(StatusBarStateController.class);
-    private final NotificationLockscreenUserManager mLockscreenUserManager
-            = Dependency.get(NotificationLockscreenUserManager.class);
+    private final SysuiStatusBarStateController mStatusBarStateController =
+            (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
+    private final NotificationLockscreenUserManager mLockscreenUserManager =
+            Dependency.get(NotificationLockscreenUserManager.class);
     private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
     private final Context mContext;
     private View mPendingWorkRemoteInputView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 86e17f3..e1a77b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -43,10 +43,11 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.RemoteInputController.Callback;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 
@@ -98,8 +99,9 @@
         mDozeParameters = dozeParameters;
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
         mLpChanged = new WindowManager.LayoutParams();
-        Dependency.get(StatusBarStateController.class).addCallback(
-                mStateListener, StatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
+        ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
+                .addCallback(mStateListener,
+                        SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index c39e172..ad4ba75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -59,15 +59,14 @@
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-
 public class StatusBarWindowView extends FrameLayout {
     public static final String TAG = "StatusBarWindowView";
     public static final boolean DEBUG = StatusBar.DEBUG;
diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
index 52cabe2..6ee341d 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
@@ -34,7 +34,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index d80b444..5d03f19 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -42,8 +42,8 @@
 import com.android.keyguard.clock.ClockManager;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 
 import org.junit.Before;
 import org.junit.Test;
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 cfc19ef..01d7b8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -44,8 +44,8 @@
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.StatusBarStateController;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index e5464e0..86f6cd3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -47,10 +47,10 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 
 import org.junit.Before;
 import org.junit.Ignore;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 56e1fc6..62700c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -95,7 +95,7 @@
 
         mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
                 mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
-                mock(StatusBarStateController.class), mEntryManager,
+                mock(StatusBarStateControllerImpl.class), mEntryManager,
                 () -> mShadeController);
         Dependency.get(InitController.class).executePostInitTasks();
         mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index db2706b..d47700b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -40,7 +40,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -99,7 +99,7 @@
         mEntry.setRow(mRow);
 
         mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
-                mEntryManager, mock(StatusBarStateController.class), mBarService,
+                mEntryManager, mock(StatusBarStateControllerImpl.class), mBarService,
                 mExpansionStateLogger);
         mLogger.setUpWithContainer(mListContainer);
         verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
@@ -167,7 +167,7 @@
         TestableNotificationLogger(NotificationListener notificationListener,
                 UiOffloadThread uiOffloadThread,
                 NotificationEntryManager entryManager,
-                StatusBarStateController statusBarStateController,
+                StatusBarStateControllerImpl statusBarStateController,
                 IStatusBarService barService,
                 ExpansionStateLogger expansionStateLogger) {
             super(notificationListener, uiOffloadThread, entryManager, statusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index ae70b01..d835082 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -51,13 +51,13 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationData;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index a72be7a..3c5425c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -32,8 +32,8 @@
 
 import com.android.systemui.R;
 import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.tuner.TunerService;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 13145b8..608dd8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -20,23 +20,15 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 
-import android.content.Context;
 import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 3b98f0c..a97fa1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -27,8 +27,9 @@
 
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -46,7 +47,7 @@
 public class NotificationPanelViewTest extends SysuiTestCase {
 
     @Mock
-    private StatusBarStateController mStatusBarStateController;
+    private SysuiStatusBarStateController mStatusBarStateController;
     @Mock
     private NotificationStackScrollLayout mNotificationStackScrollLayout;
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 036e57acb..a95361f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -82,6 +82,7 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NavigationBarController;
@@ -94,7 +95,7 @@
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -153,7 +154,7 @@
     @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private RemoteInputController mRemoteInputController;
-    @Mock private StatusBarStateController mStatusBarStateController;
+    @Mock private StatusBarStateControllerImpl mStatusBarStateController;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private NotificationPresenter mNotificationPresenter;
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 46335dc..11284d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -28,9 +28,9 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import org.junit.Before;
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 2b45b49..fb7585b 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -515,6 +515,9 @@
 
   // Total number of scan results for WPA3-Enterprise networks
   optional int32 num_wpa3_enterprise_network_scan_results = 136;
+
+  // WifiConfigStore read/write metrics.
+  optional WifiConfigStoreIO wifi_config_store_io = 137;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -1874,6 +1877,13 @@
 
   // Rx link speed at the sample time in Mbps
   optional int32 rx_link_speed_mbps = 27;
+
+  // Sequence number generated by framework
+  optional int32 seq_num_inside_framework = 28;
+
+  // Whether current entry is for the same BSSID on the same frequency compared
+  // to last entry
+  optional bool is_same_bssid_and_freq = 29;
 }
 
 message WifiUsabilityStats {
@@ -2170,3 +2180,25 @@
     EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = 9;
   }
 }
+
+// WifiConfigStore read/write metrics.
+message WifiConfigStoreIO {
+  // Histogram of config store read durations.
+  repeated DurationBucket read_durations = 1;
+
+  // Histogram of config store write durations.
+  repeated DurationBucket write_durations = 2;
+
+  // Total Number of instances of write/read duration in this duration bucket.
+  message DurationBucket {
+    // Bucket covers duration : [range_start_ms, range_end_ms)
+    // The (inclusive) lower bound of read/write duration represented by this bucket
+    optional int32 range_start_ms = 1;
+
+    // The (exclusive) upper bound of read/write duration represented by this bucket
+    optional int32 range_end_ms = 2;
+
+    // Number of read/write durations that fit into this bucket
+    optional int32 count = 3;
+  }
+}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 9249c9c..4afbc64 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -39,6 +40,7 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.util.LocalLog;
 import android.util.Slog;
@@ -89,19 +91,38 @@
     @Nullable
     private SparseBooleanArray mDisabledUsers;
 
+    /**
+     * Global kill-switch based on value defined by
+     * {@link ContentCaptureManager#DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED}.
+     */
+    @GuardedBy("mLock")
+    @Nullable
+    private boolean mDisabledByDeviceConfig;
 
     public ContentCaptureManagerService(@NonNull Context context) {
         super(context, new FrameworkResourcesServiceNameResolver(context,
                 com.android.internal.R.string.config_defaultContentCaptureService),
                 UserManager.DISALLOW_CONTENT_CAPTURE);
-        // Sets which serviecs are disabled
+        DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                ActivityThread.currentApplication().getMainExecutor(),
+                (namespace, key, value) -> {
+                    if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED
+                            .equals(key)) {
+                        Slog.i(mTag, "Ignoring change on " + key);
+                        return;
+                    }
+                    setDisabledByDeviceConfig(value);
+                });
+        setDisabledByDeviceConfig();
+
+        // Sets which services are disabled
         final UserManager um = getContext().getSystemService(UserManager.class);
         final List<UserInfo> users = um.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final int userId = users.get(i).id;
-            final boolean disabled = isDisabledBySettings(userId);
+            final boolean disabled = mDisabledByDeviceConfig || isDisabledBySettings(userId);
             if (disabled) {
-                Slog.i(mTag, "user " + userId + " disabled by settings");
+                Slog.i(mTag, "user " + userId + " disabled by settings or device config");
                 if (mDisabledUsers == null) {
                     mDisabledUsers = new SparseBooleanArray(1);
                 }
@@ -160,7 +181,8 @@
 
     @Override // from AbstractMasterSystemService
     protected boolean isDisabledLocked(@UserIdInt int userId) {
-        return isDisabledBySettingsLocked(userId) || super.isDisabledLocked(userId);
+        return mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId)
+                || super.isDisabledLocked(userId);
     }
 
     private boolean isDisabledBySettingsLocked(@UserIdInt int userId) {
@@ -191,6 +213,45 @@
         return false;
     }
 
+    private void setDisabledByDeviceConfig() {
+        final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
+        setDisabledByDeviceConfig(value);
+    }
+
+    private void setDisabledByDeviceConfig(@Nullable String value) {
+        if (verbose) Slog.v(mTag, "setDisabledByDeviceConfig(): value=" + value);
+        final UserManager um = getContext().getSystemService(UserManager.class);
+        final List<UserInfo> users = um.getUsers();
+
+        final boolean newDisabledValue;
+
+        if (value != null && value.equalsIgnoreCase("false")) {
+            newDisabledValue = true;
+        } else {
+            newDisabledValue = false;
+        }
+
+        synchronized (mLock) {
+            if (mDisabledByDeviceConfig == newDisabledValue) {
+                if (verbose) {
+                    Slog.v(mTag, "setDisabledByDeviceConfig(): already " + newDisabledValue);
+                }
+                return;
+            }
+            mDisabledByDeviceConfig = newDisabledValue;
+
+            Slog.i(mTag, "setDisabledByDeviceConfig(): set to " + mDisabledByDeviceConfig);
+            for (int i = 0; i < users.size(); i++) {
+                final int userId = users.get(i).id;
+                boolean disabled = mDisabledByDeviceConfig || isDisabledBySettingsLocked(userId);
+                Slog.i(mTag, "setDisabledByDeviceConfig(): updating service for user "
+                        + userId + " to " + (disabled ? "'disabled'" : "'enabled'"));
+                updateCachedServiceLocked(userId, disabled);
+            }
+        }
+    }
+
     private void setContentCaptureFeatureEnabledForUser(@UserIdInt int userId, boolean enabled) {
         synchronized (mLock) {
             if (mDisabledUsers == null) {
@@ -338,6 +399,8 @@
         super.dumpLocked(prefix, pw);
 
         pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers);
+        pw.print(prefix); pw.print("Disabled by DeviceConfig: ");
+        pw.println(mDisabledByDeviceConfig);
     }
 
     final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
@@ -406,7 +469,7 @@
                         "isContentCaptureFeatureEnabled()", userId, Binder.getCallingUid(), result);
                 if (!isService) return;
 
-                enabled = !isDisabledBySettingsLocked(userId);
+                enabled = !mDisabledByDeviceConfig && !isDisabledBySettingsLocked(userId);
             }
             try {
                 result.send(enabled ? ContentCaptureManager.RESULT_CODE_TRUE
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index f2329d3..e7d7434 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4013,7 +4013,7 @@
                     return;
                 }
                 userPackages.add(packageName);
-                sandboxId = getSandboxId(packageName, sharedUserId);
+                sandboxId = StorageManagerService.this.getSandboxId(packageName, sharedUserId);
             }
 
             try {
@@ -4028,7 +4028,8 @@
             if (!ENABLE_ISOLATED_STORAGE) {
                 return;
             }
-            final String sandboxId = getSandboxId(packageName, sharedUserId);
+            final String sandboxId = StorageManagerService.this.getSandboxId(
+                    packageName, sharedUserId);
             synchronized (mPackagesLock) {
                 final ArraySet<String> userPackages = mPackages.get(userId);
                 // If the userPackages is null, it means the user is not started but we still
@@ -4056,6 +4057,12 @@
             return visibleVolsForUser.toArray(new String[visibleVolsForUser.size()]);
         }
 
+        @Override
+        public String getSandboxId(String packageName) {
+            return StorageManagerService.this.getSandboxId(packageName,
+                    mPmInternal.getSharedUserIdForPackage(packageName));
+        }
+
         private String getVolumeLabel(VolumeInfo vol) {
             // STOPSHIP: Label needs to part of VolumeInfo and need to be passed on from vold
             switch (vol.getType()) {
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index c7b9a3c..eaf790b 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -82,6 +82,9 @@
     private static final String ADB_DIRECTORY = "misc/adb";
     // This file contains keys that will always be allowed to connect to the device via adb.
     private static final String ADB_KEYS_FILE = "adb_keys";
+    // This file contains keys that will be allowed to connect without user interaction as long
+    // as a subsequent connection occurs within the allowed duration.
+    private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
     private static final int BUFFER_SIZE = 4096;
 
     private final Context mContext;
@@ -263,7 +266,6 @@
 
         AdbDebuggingHandler(Looper looper) {
             super(looper);
-            mAdbKeyStore = new AdbKeyStore();
         }
 
         /**
@@ -289,6 +291,7 @@
                     mThread = new AdbDebuggingThread();
                     mThread.start();
 
+                    mAdbKeyStore = new AdbKeyStore();
                     break;
 
                 case MESSAGE_ADB_DISABLED:
@@ -303,6 +306,9 @@
                         mThread = null;
                     }
 
+                    cancelJobToUpdateAdbKeyStore();
+                    mAdbKeyStore = null;
+                    mConnectedKey = null;
                     break;
 
                 case MESSAGE_ADB_ALLOW: {
@@ -532,7 +538,11 @@
         return new File(adbDir, fileName);
     }
 
-    private File getUserKeyFile() {
+    File getAdbTempKeysFile() {
+        return getAdbFile(ADB_TEMP_KEYS_FILE);
+    }
+
+    File getUserKeyFile() {
         return getAdbFile(ADB_KEYS_FILE);
     }
 
@@ -668,9 +678,6 @@
         private Map<String, Long> mKeyMap;
         private File mKeyFile;
         private AtomicFile mAtomicKeyFile;
-        // This file contains keys that will be allowed to connect without user interaction as long
-        // as a subsequent connection occurs within the allowed duration.
-        private static final String ADB_TEMP_KEYS_FILE = "adb_temp_keys.xml";
         private static final String XML_TAG_ADB_KEY = "adbKey";
         private static final String XML_ATTRIBUTE_KEY = "key";
         private static final String XML_ATTRIBUTE_LAST_CONNECTION = "lastConnection";
@@ -704,9 +711,9 @@
          */
         private void initKeyFile() {
             if (mKeyFile == null) {
-                mKeyFile = getAdbFile(ADB_TEMP_KEYS_FILE);
+                mKeyFile = getAdbTempKeysFile();
             }
-            // getAdbFile can return null if the adb file cannot be obtained
+            // getAdbTempKeysFile can return null if the adb file cannot be obtained
             if (mKeyFile != null) {
                 mAtomicKeyFile = new AtomicFile(mKeyFile);
             }
@@ -767,7 +774,8 @@
         public void persistKeyStore() {
             // if there is nothing in the key map then ensure any keys left in the key store files
             // are deleted as well.
-            if (mKeyMap.size() == 0) {
+            filterOutOldKeys();
+            if (mKeyMap.isEmpty()) {
                 deleteKeyStore();
                 return;
             }
@@ -784,22 +792,15 @@
                 keyStream = mAtomicKeyFile.startWrite();
                 serializer.setOutput(keyStream, StandardCharsets.UTF_8.name());
                 serializer.startDocument(null, true);
-                long allowedTime = getAllowedConnectionTime();
-                long systemTime = System.currentTimeMillis();
-                Iterator keyMapIterator = mKeyMap.entrySet().iterator();
-                while (keyMapIterator.hasNext()) {
-                    Map.Entry<String, Long> keyEntry = (Map.Entry) keyMapIterator.next();
-                    long connectionTime = keyEntry.getValue();
-                    if (systemTime < (connectionTime + allowedTime)) {
-                        serializer.startTag(null, XML_TAG_ADB_KEY);
-                        serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
-                        serializer.attribute(null, XML_ATTRIBUTE_LAST_CONNECTION,
-                                String.valueOf(keyEntry.getValue()));
-                        serializer.endTag(null, XML_TAG_ADB_KEY);
-                    } else {
-                        keyMapIterator.remove();
-                    }
+
+                for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
+                    serializer.startTag(null, XML_TAG_ADB_KEY);
+                    serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
+                    serializer.attribute(null, XML_ATTRIBUTE_LAST_CONNECTION,
+                            String.valueOf(keyEntry.getValue()));
+                    serializer.endTag(null, XML_TAG_ADB_KEY);
                 }
+
                 serializer.endDocument();
                 mAtomicKeyFile.finishWrite(keyStream);
             } catch (IOException e) {
@@ -808,6 +809,19 @@
             }
         }
 
+        private void filterOutOldKeys() {
+            long allowedTime = getAllowedConnectionTime();
+            long systemTime = System.currentTimeMillis();
+            Iterator<Map.Entry<String, Long>> keyMapIterator = mKeyMap.entrySet().iterator();
+            while (keyMapIterator.hasNext()) {
+                Map.Entry<String, Long> keyEntry = keyMapIterator.next();
+                long connectionTime = keyEntry.getValue();
+                if (allowedTime != 0 && systemTime > (connectionTime + allowedTime)) {
+                    keyMapIterator.remove();
+                }
+            }
+        }
+
         /**
          * Removes all of the entries in the key map and deletes the key file.
          */
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index c316915..7fd98e0 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -45,6 +45,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Collections;
@@ -95,6 +96,16 @@
         public boolean isAdbEnabled() {
             return mAdbEnabled;
         }
+
+        @Override
+        public File getAdbKeysFile() {
+            return mDebuggingManager.getUserKeyFile();
+        }
+
+        @Override
+        public File getAdbTempKeysFile() {
+            return mDebuggingManager.getAdbTempKeysFile();
+        }
     }
 
     private final class AdbHandler extends Handler {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5932f99..60a45bf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2226,7 +2226,7 @@
         mConstants = hasHandlerThread ? new ActivityManagerConstants(this, mHandler) : null;
         final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
-        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, new Object());
+        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
         mIntentFirewall = hasHandlerThread
                 ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
@@ -2274,7 +2274,7 @@
         mConstants = new ActivityManagerConstants(this, mHandler);
         final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
-        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, atm.getGlobalLock());
+        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
         // Broadcast policy parameters
         final BroadcastConstants foreConstants = new BroadcastConstants(
@@ -6549,7 +6549,7 @@
                 conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag,
                         stable);
                 if (conn != null && (conn.stableCount+conn.unstableCount) == 1) {
-                    if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+                    if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                         // If this is a perceptible app accessing the provider,
                         // make sure to count it as being accessed and thus
                         // back up on the LRU list.  This is good because
@@ -10828,6 +10828,7 @@
             printOomLevel(pw, "FOREGROUND_APP_ADJ", ProcessList.FOREGROUND_APP_ADJ);
             printOomLevel(pw, "VISIBLE_APP_ADJ", ProcessList.VISIBLE_APP_ADJ);
             printOomLevel(pw, "PERCEPTIBLE_APP_ADJ", ProcessList.PERCEPTIBLE_APP_ADJ);
+            printOomLevel(pw, "PERCEPTIBLE_LOW_APP_ADJ", ProcessList.PERCEPTIBLE_LOW_APP_ADJ);
             printOomLevel(pw, "BACKUP_APP_ADJ", ProcessList.BACKUP_APP_ADJ);
             printOomLevel(pw, "HEAVY_WEIGHT_APP_ADJ", ProcessList.HEAVY_WEIGHT_APP_ADJ);
             printOomLevel(pw, "SERVICE_ADJ", ProcessList.SERVICE_ADJ);
@@ -10878,16 +10879,17 @@
         pw.println("  Total number of kills: " + cnt);
 
         return reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MAX_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
-            reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
+                reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_LOW_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
+                reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
     }
 
     /**
@@ -11760,7 +11762,8 @@
             ProcessList.NATIVE_ADJ,
             ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ,
             ProcessList.PERSISTENT_SERVICE_ADJ, ProcessList.FOREGROUND_APP_ADJ,
-            ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ,
+            ProcessList.VISIBLE_APP_ADJ,
+            ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_LOW_APP_ADJ,
             ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
             ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
             ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MIN_ADJ
@@ -11768,7 +11771,7 @@
     static final String[] DUMP_MEM_OOM_LABEL = new String[] {
             "Native",
             "System", "Persistent", "Persistent Service", "Foreground",
-            "Visible", "Perceptible",
+            "Visible", "Perceptible", "Perceptible Low",
             "Heavy Weight", "Backup",
             "A Services", "Home",
             "Previous", "B Services", "Cached"
@@ -11776,7 +11779,7 @@
     static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
             "native",
             "sys", "pers", "persvc", "fore",
-            "vis", "percept",
+            "vis", "percept", "perceptl",
             "heavy", "backup",
             "servicea", "home",
             "prev", "serviceb", "cached"
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index 502f078..c7e4fc7 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -55,6 +55,8 @@
     private static final int COMPACT_ACTION_FILE_FLAG = 1;
     private static final int COMPACT_ACTION_ANON_FLAG = 2;
     private static final int COMPACT_ACTION_FULL_FLAG = 3;
+    private static final int COMPACT_ACTION_NONE_FLAG = 4;
+    private static final String COMPACT_ACTION_NONE = "";
     private static final String COMPACT_ACTION_FILE = "file";
     private static final String COMPACT_ACTION_ANON = "anon";
     private static final String COMPACT_ACTION_FULL = "all";
@@ -320,6 +322,8 @@
     @VisibleForTesting
     static String compactActionIntToString(int action) {
         switch(action) {
+            case COMPACT_ACTION_NONE_FLAG:
+                return COMPACT_ACTION_NONE;
             case COMPACT_ACTION_FILE_FLAG:
                 return COMPACT_ACTION_FILE;
             case COMPACT_ACTION_ANON_FLAG:
@@ -327,7 +331,7 @@
             case COMPACT_ACTION_FULL_FLAG:
                 return COMPACT_ACTION_FULL;
             default:
-                return COMPACT_ACTION_FILE;
+                return COMPACT_ACTION_NONE;
         }
     }
 
@@ -398,6 +402,10 @@
                         action = mCompactActionFull;
                     }
 
+                    if (action.equals(COMPACT_ACTION_NONE)) {
+                        return;
+                    }
+
                     try {
                         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
                                 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7035698..93a71e5 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -127,18 +127,8 @@
     private final ActivityManagerService mService;
     private final ProcessList mProcessList;
 
-    /**
-     * Used to lock {@link #updateOomAdjImpl} for state consistency. It also reduces frequency lock
-     * and unlock when getting and setting value to {@link ProcessRecord#mWindowProcessController}.
-     * Note it is declared as Object type so the locked-region-code-injection won't wrap the
-     * unnecessary priority booster.
-     */
-    private final Object mAtmGlobalLock;
-
-    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
-            Object atmGlobalLock) {
+    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
         mService = service;
-        mAtmGlobalLock = atmGlobalLock;
         mProcessList = processList;
         mActiveUids = activeUids;
 
@@ -196,13 +186,6 @@
 
     @GuardedBy("mService")
     final void updateOomAdjLocked() {
-        synchronized (mAtmGlobalLock) {
-            updateOomAdjImpl();
-        }
-    }
-
-    @GuardedBy({"mService", "mAtmGlobalLock"})
-    private void updateOomAdjImpl() {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "updateOomAdj");
         mService.mOomAdjProfiler.oomAdjStarted();
         final ProcessRecord TOP_APP = mService.getTopAppLocked();
@@ -1224,8 +1207,8 @@
                                     }
                                 } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
-                                        && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
-                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
+                                        && adj > ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+                                    newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                         && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -1610,7 +1593,7 @@
         //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
         if (adj > app.maxAdj) {
             adj = app.maxAdj;
-            if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+            if (app.maxAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 69cf54b..f01305e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -183,6 +183,10 @@
     // is not entirely fatal but is generally a bad idea.
     static final int BACKUP_APP_ADJ = 300;
 
+    // This is a process bound by the system that's more important than services but not so
+    // perceptible that it affects the user immediately if killed.
+    static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
+
     // This is a process only hosting components that are perceptible to the
     // user, and we really want to avoid killing them, but they are not
     // immediately visible. An example is background music playback.
@@ -717,6 +721,9 @@
         } else if (setAdj >= ProcessList.BACKUP_APP_ADJ) {
             return buildOomTag("bkup  ", "bkup", null, setAdj,
                     ProcessList.BACKUP_APP_ADJ, compact);
+        } else if (setAdj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+            return buildOomTag("prcl  ", "prcl", null, setAdj,
+                    ProcessList.PERCEPTIBLE_LOW_APP_ADJ, compact);
         } else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
             return buildOomTag("prcp  ", "prcp", null, setAdj,
                     ProcessList.PERCEPTIBLE_APP_ADJ, compact);
@@ -1740,8 +1747,11 @@
         try {
             final String[] packageNames = mService.mContext.getPackageManager()
                     .getPackagesForUid(uid);
-            final String[] visibleVolIds = LocalServices.getService(StorageManagerInternal.class)
+            final StorageManagerInternal storageManagerInternal =
+                    LocalServices.getService(StorageManagerInternal.class);
+            final String[] visibleVolIds = storageManagerInternal
                     .getVisibleVolumesForUser(UserHandle.getUserId(uid));
+            final String sandboxId = storageManagerInternal.getSandboxId(app.info.packageName);
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
             checkSlow(startTime, "startProcess: asking zygote to start proc");
@@ -1751,7 +1761,7 @@
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
-                        packageNames, visibleVolIds,
+                        packageNames, visibleVolIds, sandboxId,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             } else if (hostingType.equals("app_zygote")) {
                 final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
@@ -1760,14 +1770,14 @@
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
-                        packageNames, visibleVolIds, /*useBlastulaPool=*/ false,
+                        packageNames, visibleVolIds, sandboxId, /*useBlastulaPool=*/ false,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName,
-                        packageNames, visibleVolIds,
+                        packageNames, visibleVolIds, sandboxId,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 5dccaf1..fcc857b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -713,6 +713,8 @@
                 adj = ProcessList.VISIBLE_APP_ADJ;
             } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+            } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+                adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
             } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
                 adj = ProcessList.CACHED_APP_MIN_ADJ;
             } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 0dc73d9..6df60d6 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -21,6 +21,8 @@
 import android.annotation.NonNull;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -424,11 +426,28 @@
     }
 
     /*package*/ void postDisconnectHearingAid() {
-        sendMsgNoDelay(MSG_DISCONNECT_HEARING_AID, SENDMSG_QUEUE);
+        sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE);
     }
 
     /*package*/ void postDisconnectHeadset() {
-        sendMsgNoDelay(MSG_DISCONNECT_HEADSET, SENDMSG_QUEUE);
+        sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE);
+    }
+
+    /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) {
+        sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile);
+    }
+
+    /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) {
+        sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile);
+    }
+
+    /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) {
+        sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile);
+    }
+
+    /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) {
+        sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE,
+                hearingAidProfile);
     }
 
     //---------------------------------------------------------------------
@@ -460,16 +479,14 @@
         }
     }
 
+    @GuardedBy("mDeviceStateLock")
     /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
                 @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
         final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
                 ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
-        final int delay;
-        synchronized (mDeviceStateLock) {
-            delay = mDeviceInventory.checkSendBecomingNoisyIntent(
+        final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
                     AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
                     AudioSystem.DEVICE_NONE);
-        }
         final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();
 
         if (AudioService.DEBUG_DEVICES) {
@@ -719,16 +736,36 @@
                         mDeviceInventory.disconnectA2dpSink();
                     }
                     break;
-                case MSG_DISCONNECT_HEARING_AID:
+                case MSG_DISCONNECT_BT_HEARING_AID:
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.disconnectHearingAid();
                     }
                     break;
-                case MSG_DISCONNECT_HEADSET:
+                case MSG_DISCONNECT_BT_HEADSET:
                     synchronized (mDeviceStateLock) {
                         mBtHelper.disconnectHeadset();
                     }
                     break;
+                case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP:
+                    synchronized (mDeviceStateLock) {
+                        mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj);
+                    }
+                    break;
+                case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK:
+                    synchronized (mDeviceStateLock) {
+                        mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj);
+                    }
+                    break;
+                case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID:
+                    synchronized (mDeviceStateLock) {
+                        mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj);
+                    }
+                    break;
+                case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET:
+                    synchronized (mDeviceStateLock) {
+                        mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj);
+                    }
+                    break;
                 default:
                     Log.wtf(TAG, "Invalid message " + msg.what);
             }
@@ -766,8 +803,12 @@
     private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
     private static final int MSG_DISCONNECT_A2DP = 19;
     private static final int MSG_DISCONNECT_A2DP_SINK = 20;
-    private static final int MSG_DISCONNECT_HEARING_AID = 21;
-    private static final int MSG_DISCONNECT_HEADSET = 22;
+    private static final int MSG_DISCONNECT_BT_HEARING_AID = 21;
+    private static final int MSG_DISCONNECT_BT_HEADSET = 22;
+    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23;
+    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
+    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
+    private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
 
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index e918997..58c1882 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -393,6 +393,84 @@
         mBluetoothHeadset = null;
     }
 
+    /*package*/ synchronized void onA2dpProfileConnected(BluetoothA2dp a2dp) {
+        mA2dp = a2dp;
+        final List<BluetoothDevice> deviceList = mA2dp.getConnectedDevices();
+        if (deviceList.isEmpty()) {
+            return;
+        }
+        final BluetoothDevice btDevice = deviceList.get(0);
+        final @BluetoothProfile.BtProfileState int state = mA2dp.getConnectionState(btDevice);
+        mDeviceBroker.handleSetA2dpSinkConnectionState(
+                state, new BluetoothA2dpDeviceInfo(btDevice));
+    }
+
+    /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
+        final List<BluetoothDevice> deviceList = profile.getConnectedDevices();
+        if (deviceList.isEmpty()) {
+            return;
+        }
+        final BluetoothDevice btDevice = deviceList.get(0);
+        final @BluetoothProfile.BtProfileState int state =
+                profile.getConnectionState(btDevice);
+        mDeviceBroker.postSetA2dpSourceConnectionState(
+                state, new BluetoothA2dpDeviceInfo(btDevice));
+    }
+
+    /*package*/ synchronized void onHearingAidProfileConnected(BluetoothHearingAid hearingAid) {
+        mHearingAid = hearingAid;
+        final List<BluetoothDevice> deviceList = mHearingAid.getConnectedDevices();
+        if (deviceList.isEmpty()) {
+            return;
+        }
+        final BluetoothDevice btDevice = deviceList.get(0);
+        final @BluetoothProfile.BtProfileState int state =
+                mHearingAid.getConnectionState(btDevice);
+        mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
+                btDevice, state,
+                /*suppressNoisyIntent*/ false,
+                /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
+                /*eventSource*/ "mBluetoothProfileServiceListener");
+    }
+
+    /*package*/ synchronized void onHeadsetProfileConnected(BluetoothHeadset headset) {
+        // Discard timeout message
+        mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
+        mBluetoothHeadset = headset;
+        setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
+        // Refresh SCO audio state
+        checkScoAudioState();
+        if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
+                && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) {
+            return;
+        }
+        boolean status = false;
+        if (mBluetoothHeadsetDevice != null) {
+            switch (mScoAudioState) {
+                case SCO_STATE_ACTIVATE_REQ:
+                    status = connectBluetoothScoAudioHelper(
+                            mBluetoothHeadset,
+                            mBluetoothHeadsetDevice, mScoAudioMode);
+                    if (status) {
+                        mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
+                    }
+                    break;
+                case SCO_STATE_DEACTIVATE_REQ:
+                    status = disconnectBluetoothScoAudioHelper(
+                            mBluetoothHeadset,
+                            mBluetoothHeadsetDevice, mScoAudioMode);
+                    if (status) {
+                        mScoAudioState = SCO_STATE_DEACTIVATING;
+                    }
+                    break;
+            }
+        }
+        if (!status) {
+            mScoAudioState = SCO_STATE_INACTIVE;
+            broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+        }
+    }
+
     //----------------------------------------------------------------------
     private void broadcastScoConnectionState(int state) {
         mDeviceBroker.postBroadcastScoConnectionState(state);
@@ -462,99 +540,36 @@
         }
     }
 
+    // NOTE this listener is NOT called from AudioDeviceBroker event thread, only call async
+    //      methods inside listener.
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
             new BluetoothProfile.ServiceListener() {
                 public void onServiceConnected(int profile, BluetoothProfile proxy) {
-                    final BluetoothDevice btDevice;
-                    List<BluetoothDevice> deviceList;
                     switch(profile) {
                         case BluetoothProfile.A2DP:
-                            synchronized (BtHelper.this) {
-                                mA2dp = (BluetoothA2dp) proxy;
-                                deviceList = mA2dp.getConnectedDevices();
-                                if (deviceList.size() > 0) {
-                                    btDevice = deviceList.get(0);
-                                    if (btDevice == null) {
-                                        Log.e(TAG, "Invalid null device in BT profile listener");
-                                        return;
-                                    }
-                                    final @BluetoothProfile.BtProfileState int state =
-                                            mA2dp.getConnectionState(btDevice);
-                                    mDeviceBroker.handleSetA2dpSinkConnectionState(
-                                            state, new BluetoothA2dpDeviceInfo(btDevice));
-                                }
-                            }
+                            AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "BT profile service: connecting A2DP profile"));
+                            mDeviceBroker.postBtA2dpProfileConnected((BluetoothA2dp) proxy);
                             break;
 
                         case BluetoothProfile.A2DP_SINK:
-                            deviceList = proxy.getConnectedDevices();
-                            if (deviceList.size() > 0) {
-                                btDevice = deviceList.get(0);
-                                final @BluetoothProfile.BtProfileState int state =
-                                        proxy.getConnectionState(btDevice);
-                                mDeviceBroker.postSetA2dpSourceConnectionState(
-                                        state, new BluetoothA2dpDeviceInfo(btDevice));
-                            }
+                            AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "BT profile service: connecting A2DP_SINK profile"));
+                            mDeviceBroker.postBtA2dpSinkProfileConnected(proxy);
                             break;
 
                         case BluetoothProfile.HEADSET:
-                            synchronized (BtHelper.this) {
-                                // Discard timeout message
-                                mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
-                                mBluetoothHeadset = (BluetoothHeadset) proxy;
-                                setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
-                                // Refresh SCO audio state
-                                checkScoAudioState();
-                                // Continue pending action if any
-                                if (mScoAudioState == SCO_STATE_ACTIVATE_REQ
-                                        || mScoAudioState == SCO_STATE_DEACTIVATE_REQ) {
-                                    boolean status = false;
-                                    if (mBluetoothHeadsetDevice != null) {
-                                        switch (mScoAudioState) {
-                                            case SCO_STATE_ACTIVATE_REQ:
-                                                status = connectBluetoothScoAudioHelper(
-                                                        mBluetoothHeadset,
-                                                        mBluetoothHeadsetDevice, mScoAudioMode);
-                                                if (status) {
-                                                    mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
-                                                }
-                                                break;
-                                            case SCO_STATE_DEACTIVATE_REQ:
-                                                status = disconnectBluetoothScoAudioHelper(
-                                                        mBluetoothHeadset,
-                                                        mBluetoothHeadsetDevice, mScoAudioMode);
-                                                if (status) {
-                                                    mScoAudioState = SCO_STATE_DEACTIVATING;
-                                                }
-                                                break;
-                                        }
-                                    }
-                                    if (!status) {
-                                        mScoAudioState = SCO_STATE_INACTIVE;
-                                        broadcastScoConnectionState(
-                                                AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
-                                    }
-                                }
-                            }
+                            AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "BT profile service: connecting HEADSET profile"));
+                            mDeviceBroker.postBtHeasetProfileConnected((BluetoothHeadset) proxy);
                             break;
 
                         case BluetoothProfile.HEARING_AID:
-                            synchronized (BtHelper.this) {
-                                mHearingAid = (BluetoothHearingAid) proxy;
-                                deviceList = mHearingAid.getConnectedDevices();
-                                if (deviceList.size() > 0) {
-                                    btDevice = deviceList.get(0);
-                                    final @BluetoothProfile.BtProfileState int state =
-                                            mHearingAid.getConnectionState(btDevice);
-                                    mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
-                                            btDevice, state,
-                                            /*suppressNoisyIntent*/ false,
-                                            /*musicDevice*/ android.media.AudioSystem.DEVICE_NONE,
-                                            /*eventSource*/ "mBluetoothProfileServiceListener");
-                                }
-                            }
+                            AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                                    "BT profile service: connecting HEARING_AID profile"));
+                            mDeviceBroker.postBtHearingAidProfileConnected(
+                                    (BluetoothHearingAid) proxy);
                             break;
-
                         default:
                             break;
                     }
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index b50b800..bca84f7 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -391,10 +391,11 @@
         private final Random mRandom = new Random();
 
         // TODO(b/123378871): Remove when moved.
-        // When BiometricPrompt#setEnableFallback is set to true, we need to store the client (app)
-        // receiver. BiometricService internally launches CDCA which invokes BiometricService to
-        // start authentication (normal path). When auth is success/rejected, CDCA will use an aidl
-        // method to poke BiometricService - the result will then be forwarded to this receiver.
+        // When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
+        // client (app) receiver. BiometricService internally launches CDCA which invokes
+        // BiometricService to start authentication (normal path). When auth is success/rejected,
+        // CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
+        // to this receiver.
         private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
 
         // The current authentication session, null if idle/done. We need to track both the current
@@ -803,11 +804,21 @@
             // we can't get activity results. Store the receiver somewhere so we can forward the
             // result back to the client.
             // TODO(b/123378871): Remove when moved.
-            if (bundle.getBoolean(BiometricPrompt.KEY_ENABLE_FALLBACK)) {
+            if (bundle.getBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL)) {
                 mHandler.post(() -> {
-                    mConfirmDeviceCredentialReceiver = receiver;
                     final KeyguardManager kgm = getContext().getSystemService(
                             KeyguardManager.class);
+                    if (!kgm.isDeviceSecure()) {
+                        try {
+                            receiver.onError(BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
+                                    getContext().getString(
+                                            R.string.biometric_error_device_not_secured));
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Remote exception", e);
+                        }
+                        return;
+                    }
+                    mConfirmDeviceCredentialReceiver = receiver;
                     // Use this so we don't need to duplicate logic..
                     final Intent intent = kgm.createConfirmDeviceCredentialIntent(null /* title */,
                             null /* description */);
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index b65535a..9e0f2fc 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -624,7 +624,8 @@
         handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                 0 /*vendorCode */);
 
-        StatsLog.write(StatsLog.BIOMETRIC_HAL_DEATH_REPORTED, statsModality());
+        StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
+                BiometricsProtoEnums.ISSUE_HAL_DEATH);
     }
 
     protected ClientMonitor getCurrentClient() {
diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
index 91c924d..3b75b95 100644
--- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
@@ -28,7 +28,7 @@
 public abstract class LoggableMonitor {
 
     public static final String TAG = "BiometricStats";
-    public static final boolean DEBUG = true;
+    public static final boolean DEBUG = false;
 
     private long mFirstAcquireTimeMs;
 
@@ -137,6 +137,8 @@
                     + ", RequireConfirmation: " + requireConfirmation
                     + ", State: " + authState
                     + ", Latency: " + latency);
+        } else {
+            Slog.v(TAG, "Authentication latency: " + latency);
         }
 
         StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 017503a..8995068 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -705,6 +705,8 @@
     public void serviceDied(long cookie) {
         super.serviceDied(cookie);
         mDaemon = null;
+
+        mCurrentUserId = UserHandle.USER_NULL; // Force updateActiveGroup() to re-evaluate
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 9e0a1c0c..d8544e3 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -49,6 +49,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
+import android.util.StatsLog;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
@@ -554,6 +555,8 @@
                         + " " + f.getDeviceId());
                 FingerprintUtils.getInstance().removeBiometricForUser(getContext(),
                         getTargetUserId(), f.getBiometricId());
+                StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
+                        BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK);
             }
             mEnrolledList.clear();
         }
@@ -1003,6 +1006,8 @@
                     mHalDeviceId, mToken, new ServiceListenerImpl(null), uf.f.getBiometricId(),
                     uf.f.getGroupId(), uf.userId, restricted, getContext().getOpPackageName());
             removeInternal(client);
+            StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
+                    BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL);
         } else {
             clearEnumerateState();
         }
diff --git a/services/core/java/com/android/server/location/LocationBasedCountryDetector.java b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
index 6527899f..8ee1285 100644
--- a/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
+++ b/services/core/java/com/android/server/location/LocationBasedCountryDetector.java
@@ -235,18 +235,15 @@
      * Start a new thread to query the country from Geocoder.
      */
     private synchronized void queryCountryCode(final Location location) {
-        if (location == null) {
-            notifyListener(null);
-            return;
-        }
         if (mQueryThread != null) return;
         mQueryThread = new Thread(new Runnable() {
             @Override
             public void run() {
-                String countryIso = null;
-                if (location != null) {
-                    countryIso = getCountryFromLocation(location);
+                if (location == null) {
+                    notifyListener(null);
+                    return;
                 }
+                String countryIso = getCountryFromLocation(location);
                 if (countryIso != null) {
                     mDetectedCountry = new Country(countryIso, Country.COUNTRY_SOURCE_LOCATION);
                 } else {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index eaedec5..874d1a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16321,7 +16321,6 @@
         final boolean onExternal = args.volumeUuid != null;
         final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
         final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
-        final boolean forceSdk = ((installFlags & PackageManager.INSTALL_FORCE_SDK) != 0);
         final boolean virtualPreload =
                 ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
         @ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
@@ -16353,8 +16352,7 @@
         // Retrieve PackageSettings and parse package
         @ParseFlags final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
                 | PackageParser.PARSE_ENFORCE_CODE
-                | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
-                | (forceSdk ? PackageParser.PARSE_FORCE_SDK : 0);
+                | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
 
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
@@ -16775,19 +16773,6 @@
                                 "replacePackageLI: new=" + pkg + ", old=" + oldPackage);
                     }
 
-                    // don't allow upgrade to target a release SDK from a pre-release SDK
-                    final boolean oldTargetsPreRelease = oldPackage.applicationInfo.targetSdkVersion
-                            == Build.VERSION_CODES.CUR_DEVELOPMENT;
-                    final boolean newTargetsPreRelease = pkg.applicationInfo.targetSdkVersion
-                            == Build.VERSION_CODES.CUR_DEVELOPMENT;
-                    if (oldTargetsPreRelease
-                            && !newTargetsPreRelease
-                            && ((parseFlags & PackageParser.PARSE_FORCE_SDK) == 0)) {
-                        Slog.w(TAG, "Can't install package targeting released sdk");
-                        throw new PrepareFailure(
-                                PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE);
-                    }
-
                     ps = mSettings.mPackages.get(pkgName11);
                     disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index dc18dfc..2eb762b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2383,8 +2383,7 @@
                         sessionParams.volumeUuid = null;
                     }
                     break;
-                case "--force-sdk":
-                    sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
+                case "--force-sdk": // ignore
                     break;
                 case "--apex":
                     sessionParams.setInstallAsApex();
@@ -2961,8 +2960,6 @@
         pw.println("          0=unknown, 1=admin policy, 2=device restore,");
         pw.println("          3=device setup, 4=user request");
         pw.println("      --force-uuid: force install on to disk volume with given UUID");
-        pw.println("      --force-sdk: allow install even when existing app targets platform");
-        pw.println("          codename but new one targets a final API level");
         pw.println("      --apex: install an .apex file, not an .apk");
         pw.println("");
         pw.println("  install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 89aea36..fa8360b 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -220,6 +220,7 @@
             session.setStagedSessionFailed(
                     SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                     "APEX staging failed, check logcat messages from apexd for more details.");
+            return;
         }
 
         if (apexInfoList.apexInfos != null && apexInfoList.apexInfos.length > 0) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 23705db..9948a3a 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -480,10 +480,13 @@
             final String apkPath = pkg.baseCodePath;
             final ApplicationInfo appInfo = pkg.applicationInfo;
             final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex";
-            if (appInfo.isPrivilegedApp() || appInfo.isEmbeddedDexUsed()) {
+            if (appInfo.isPrivilegedApp() || appInfo.isEmbeddedDexUsed()
+                    || appInfo.isDefaultToDeviceProtectedStorage()) {
                 // Privileged apps prefer to load trusted code so they don't use compiled views.
                 // If the app is not privileged but prefers code integrity, also avoid compiling
                 // views.
+                // Also disable the view compiler for protected storage apps since there are
+                // selinux permissions required for writing to user_de.
                 return false;
             }
             Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index e7de8dd..3534cf3 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -67,8 +67,8 @@
                         mContext.getContentResolver(),
                         Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
 
-                // TODO: STOPSHIP: Remove the following code once we remove default_sms_application
-                // and use the new config_defaultRoleHolders.
+                // TODO: STOPSHIP: Remove the following code once we read the value of
+                //  config_defaultSms in RoleControllerService.
                 if (result == null) {
                     Collection<SmsApplication.SmsApplicationData> applications =
                             SmsApplication.getApplicationCollectionAsUser(mContext, userId);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index af3bff0..1782b6a 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -197,7 +197,8 @@
     // System Property indicating that retail demo mode is currently enabled.
     private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
 
-    // Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
+    // Possible reasons for shutting down or reboot for use in REBOOT_PROPERTY(sys.boot.reason)
+    // which is set by bootstat
     private static final String REASON_SHUTDOWN = "shutdown";
     private static final String REASON_REBOOT = "reboot";
     private static final String REASON_USERREQUESTED = "shutdown,userrequested";
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 3586772..dd2cda2 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -45,6 +45,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsService;
@@ -1419,23 +1421,35 @@
         }
     }
 
-    private void pullNumFingerprints(int tagId, long elapsedNanos, long wallClockNanos,
-            List<StatsLogEventWrapper> pulledData) {
+    private void pullNumBiometricsEnrolled(int modality, int tagId, long elapsedNanos,
+            long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
         FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
-        if (fingerprintManager == null) {
+        FaceManager faceManager = mContext.getSystemService(FaceManager.class);
+        if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT && fingerprintManager == null) {
+            return;
+        }
+        if (modality == BiometricsProtoEnums.MODALITY_FACE && faceManager == null) {
             return;
         }
         UserManager userManager = mContext.getSystemService(UserManager.class);
         if (userManager == null) {
             return;
         }
+
         final long token = Binder.clearCallingIdentity();
         for (UserInfo user : userManager.getUsers()) {
             final int userId = user.getUserHandle().getIdentifier();
-            final int numFingerprints = fingerprintManager.getEnrolledFingerprints(userId).size();
+            int numEnrolled = 0;
+            if (modality == BiometricsProtoEnums.MODALITY_FINGERPRINT) {
+                numEnrolled = fingerprintManager.getEnrolledFingerprints(userId).size();
+            } else if (modality == BiometricsProtoEnums.MODALITY_FACE) {
+                numEnrolled = faceManager.getEnrolledFaces(userId).size();
+            } else {
+                return;
+            }
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
             e.writeInt(userId);
-            e.writeInt(numFingerprints);
+            e.writeInt(numEnrolled);
             pulledData.add(e);
         }
         Binder.restoreCallingIdentity(token);
@@ -2027,7 +2041,13 @@
                 break;
             }
             case StatsLog.NUM_FINGERPRINTS_ENROLLED: {
-                pullNumFingerprints(tagId, elapsedNanos, wallClockNanos, ret);
+                pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FINGERPRINT, tagId,
+                        elapsedNanos, wallClockNanos, ret);
+                break;
+            }
+            case StatsLog.NUM_FACES_ENROLLED: {
+                pullNumBiometricsEnrolled(BiometricsProtoEnums.MODALITY_FACE, tagId, elapsedNanos,
+                        wallClockNanos, ret);
                 break;
             }
             case StatsLog.PROC_STATS: {
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 4adce58..ec62ec7 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
+import android.debug.AdbManagerInternal;
 import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.IBinder;
@@ -42,6 +43,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -49,7 +51,6 @@
 import java.io.PrintWriter;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.attribute.PosixFilePermission;
 import java.util.Set;
 
@@ -85,6 +86,7 @@
                 break;
             case PHASE_BOOT_COMPLETED:
                 disableAutoSync();
+                configureSettings();
                 break;
         }
         super.onBootPhase(phase);
@@ -98,31 +100,19 @@
             return;
         }
         mShouldSetUpTestHarnessMode = true;
+        setUpAdb(testHarnessModeData);
+        setDeviceProvisioned();
+    }
+
+    private void setUpAdb(byte[] testHarnessModeData) {
+        ContentResolver cr = getContext().getContentResolver();
+        // Disable the TTL for ADB keys before enabling ADB
+        Settings.Global.putLong(cr, Settings.Global.ADB_ALLOWED_CONNECTION_TIME, 0);
+
         PersistentData persistentData = PersistentData.fromBytes(testHarnessModeData);
 
         SystemProperties.set(TEST_HARNESS_MODE_PROPERTY, persistentData.mEnabled ? "1" : "0");
         writeAdbKeysFile(persistentData);
-        // Clear out the data block so that we don't revert the ADB keys on every boot.
-        getPersistentDataBlock().clearTestHarnessModeData();
-
-        ContentResolver cr = getContext().getContentResolver();
-        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 0) {
-            // Enable ADB
-            Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1);
-        } else {
-            // ADB is already enabled, we should restart the service so it picks up the new keys
-            android.os.SystemService.restart("adbd");
-        }
-
-        Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-        Settings.Global.putInt(
-                cr,
-                Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
-                BatteryManager.BATTERY_PLUGGED_ANY);
-        Settings.Global.putInt(cr, Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE, 1);
-        Settings.Global.putInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
-
-        setDeviceProvisioned();
     }
 
     private void disableAutoSync() {
@@ -134,11 +124,36 @@
             .setMasterSyncAutomaticallyAsUser(false, primaryUser.getUserHandle().getIdentifier());
     }
 
+    private void configureSettings() {
+        if (!mShouldSetUpTestHarnessMode) {
+            return;
+        }
+        ContentResolver cr = getContext().getContentResolver();
+
+        Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 1);
+        Settings.Global.putInt(cr, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1);
+        Settings.Global.putInt(cr, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
+        Settings.Global.putInt(
+                cr,
+                Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
+                BatteryManager.BATTERY_PLUGGED_ANY);
+        Settings.Global.putInt(cr, Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE, 1);
+    }
+
     private void writeAdbKeysFile(PersistentData persistentData) {
-        Path adbKeys = Paths.get("/data/misc/adb/adb_keys");
+        AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
+
+        writeBytesToFile(persistentData.mAdbKeys, adbManager.getAdbKeysFile().toPath());
+        writeBytesToFile(persistentData.mAdbTempKeys, adbManager.getAdbTempKeysFile().toPath());
+
+        // Clear out the data block so that we don't revert the ADB keys on every boot.
+        getPersistentDataBlock().clearTestHarnessModeData();
+    }
+
+    private void writeBytesToFile(byte[] keys, Path adbKeys) {
         try {
             OutputStream fileOutputStream = Files.newOutputStream(adbKeys);
-            fileOutputStream.write(persistentData.mAdbKeys);
+            fileOutputStream.write(keys);
             fileOutputStream.close();
 
             Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(adbKeys);
@@ -219,23 +234,22 @@
         }
 
         private int handleEnable() {
-            Path adbKeys = Paths.get("/data/misc/adb/adb_keys");
-            if (!Files.exists(adbKeys)) {
+            AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
+            File adbKeys = adbManager.getAdbKeysFile();
+            File adbTempKeys = adbManager.getAdbTempKeysFile();
+            if (adbKeys == null && adbTempKeys == null) {
                 // This should only be accessible on eng builds that haven't yet set up ADB keys
                 getErrPrintWriter()
                     .println("No ADB keys stored; not enabling test harness mode");
                 return 1;
             }
 
-            try (InputStream inputStream = Files.newInputStream(adbKeys)) {
-                long size = Files.size(adbKeys);
-                byte[] adbKeysBytes = new byte[(int) size];
-                int numBytes = inputStream.read(adbKeysBytes);
-                if (numBytes != size) {
-                    getErrPrintWriter().println("Failed to read all bytes of adb_keys");
-                    return 1;
-                }
-                PersistentData persistentData = new PersistentData(true, adbKeysBytes);
+            try {
+                byte[] adbKeysBytes = getBytesFromFile(adbKeys);
+                byte[] adbTempKeysBytes = getBytesFromFile(adbTempKeys);
+
+                PersistentData persistentData =
+                        new PersistentData(true, adbKeysBytes, adbTempKeysBytes);
                 getPersistentDataBlock().setTestHarnessModeData(persistentData.toBytes());
             } catch (IOException e) {
                 Slog.e(TAG, "Failed to store ADB keys.", e);
@@ -252,6 +266,22 @@
             return 0;
         }
 
+        private byte[] getBytesFromFile(File file) throws IOException {
+            if (file == null || !file.exists()) {
+                return new byte[0];
+            }
+            Path path = file.toPath();
+            try (InputStream inputStream = Files.newInputStream(path)) {
+                int size = (int) Files.size(path);
+                byte[] bytes = new byte[size];
+                int numBytes = inputStream.read(bytes);
+                if (numBytes != size) {
+                    throw new IOException("Failed to read the whole file");
+                }
+                return bytes;
+            }
+        }
+
         @Override
         public void onHelp() {
             PrintWriter pw = getOutPrintWriter();
@@ -290,15 +320,17 @@
         final int mVersion;
         final boolean mEnabled;
         final byte[] mAdbKeys;
+        final byte[] mAdbTempKeys;
 
-        PersistentData(boolean enabled, byte[] adbKeys) {
-            this(VERSION_1, enabled, adbKeys);
+        PersistentData(boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
+            this(VERSION_1, enabled, adbKeys, adbTempKeys);
         }
 
-        PersistentData(int version, boolean enabled, byte[] adbKeys) {
+        PersistentData(int version, boolean enabled, byte[] adbKeys, byte[] adbTempKeys) {
             this.mVersion = version;
             this.mEnabled = enabled;
             this.mAdbKeys = adbKeys;
+            this.mAdbTempKeys = adbTempKeys;
         }
 
         static PersistentData fromBytes(byte[] bytes) {
@@ -309,7 +341,10 @@
                 int adbKeysLength = is.readInt();
                 byte[] adbKeys = new byte[adbKeysLength];
                 is.readFully(adbKeys);
-                return new PersistentData(version, enabled, adbKeys);
+                int adbTempKeysLength = is.readInt();
+                byte[] adbTempKeys = new byte[adbTempKeysLength];
+                is.readFully(adbTempKeys);
+                return new PersistentData(version, enabled, adbKeys, adbTempKeys);
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
@@ -323,6 +358,8 @@
                 dos.writeBoolean(mEnabled);
                 dos.writeInt(mAdbKeys.length);
                 dos.write(mAdbKeys);
+                dos.writeInt(mAdbTempKeys.length);
+                dos.write(mAdbTempKeys);
                 dos.close();
                 return os.toByteArray();
             } catch (IOException e) {
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 62421ac..f882fde 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -40,6 +40,7 @@
 import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.am.ActivityDisplayProto.STACKS;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
@@ -575,7 +576,8 @@
             final ActivityStack stack = mStacks.get(stackNdx);
             final ActivityRecord resumedActivity = stack.getResumedActivity();
             if (resumedActivity != null
-                    && (!stack.shouldBeVisible(resuming) || !stack.isFocusable())) {
+                    && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
+                        || !stack.isFocusable())) {
                 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                         " mResumedActivity=" + resumedActivity);
                 someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ef40648..4faf910 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -109,6 +109,7 @@
 import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
 import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
 import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
@@ -2054,8 +2055,10 @@
      * @param activeActivity the activity that is active or just completed pause action. We won't
      *                       resume if this activity is active.
      */
-    private boolean shouldResumeActivity(ActivityRecord activeActivity) {
-        return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED);
+    @VisibleForTesting
+    boolean shouldResumeActivity(ActivityRecord activeActivity) {
+        return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
+                && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6f07be8..cc78588 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -108,6 +108,7 @@
 
 import static java.lang.Integer.MAX_VALUE;
 
+import android.annotation.IntDef;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -223,6 +224,22 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
+    @IntDef(prefix = {"STACK_VISIBILITY"}, value = {
+            STACK_VISIBILITY_VISIBLE,
+            STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+            STACK_VISIBILITY_INVISIBLE,
+    })
+    @interface StackVisibility {}
+
+    /** Stack is visible. No other stacks on top that fully or partially occlude it. */
+    static final int STACK_VISIBILITY_VISIBLE = 0;
+
+    /** Stack is partially occluded by other translucent stack(s) on top of it. */
+    static final int STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1;
+
+    /** Stack is completely invisible. */
+    static final int STACK_VISIBILITY_INVISIBLE = 2;
+
     @Override
     protected int getChildCount() {
         return mTaskHistory.size();
@@ -1959,14 +1976,28 @@
      * @param starting The currently starting activity or null if there is none.
      */
     boolean shouldBeVisible(ActivityRecord starting) {
+        return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
+    }
+
+    /**
+     * Returns true if the stack should be visible.
+     *
+     * @param starting The currently starting activity or null if there is none.
+     */
+    @StackVisibility
+    int getVisibility(ActivityRecord starting) {
         if (!isAttached() || mForceHidden) {
-            return false;
+            return STACK_VISIBILITY_INVISIBLE;
         }
 
         final ActivityDisplay display = getDisplay();
         boolean gotSplitScreenStack = false;
         boolean gotOpaqueSplitScreenPrimary = false;
         boolean gotOpaqueSplitScreenSecondary = false;
+        boolean gotTranslucentFullscreen = false;
+        boolean gotTranslucentSplitScreenPrimary = false;
+        boolean gotTranslucentSplitScreenSecondary = false;
+        boolean shouldBeVisible = true;
         final int windowingMode = getWindowingMode();
         final boolean isAssistantType = isActivityTypeAssistant();
         for (int i = display.getChildCount() - 1; i >= 0; --i) {
@@ -1975,8 +2006,9 @@
             if (other == this) {
                 // Should be visible if there is no other stack occluding it, unless it doesn't
                 // have any running activities, not starting one and not home stack.
-                return hasRunningActivities || isInStackLocked(starting) != null
+                shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null
                         || isActivityTypeHome();
+                break;
             }
 
             if (!hasRunningActivities) {
@@ -1996,51 +2028,79 @@
                 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                     if (activityType == ACTIVITY_TYPE_HOME
                             || (activityType == ACTIVITY_TYPE_ASSISTANT
-                                    && mWindowManager.getRecentsAnimationController() != null)) {
-                       return true;
+                                && mWindowManager.getRecentsAnimationController() != null)) {
+                        break;
                     }
                 }
                 if (other.isStackTranslucent(starting)) {
                     // Can be visible behind a translucent fullscreen stack.
+                    gotTranslucentFullscreen = true;
                     continue;
                 }
-                return false;
+                return STACK_VISIBILITY_INVISIBLE;
             } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                     && !gotOpaqueSplitScreenPrimary) {
                 gotSplitScreenStack = true;
-                gotOpaqueSplitScreenPrimary =
-                        !other.isStackTranslucent(starting);
+                gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting);
+                gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
                 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
                         && gotOpaqueSplitScreenPrimary) {
                     // Can not be visible behind another opaque stack in split-screen-primary mode.
-                    return false;
+                    return STACK_VISIBILITY_INVISIBLE;
                 }
             } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                     && !gotOpaqueSplitScreenSecondary) {
                 gotSplitScreenStack = true;
-                gotOpaqueSplitScreenSecondary =
-                        !other.isStackTranslucent(starting);
+                gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting);
+                gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
                 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
                         && gotOpaqueSplitScreenSecondary) {
                     // Can not be visible behind another opaque stack in split-screen-secondary mode.
-                    return false;
+                    return STACK_VISIBILITY_INVISIBLE;
                 }
             }
             if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
                 // Can not be visible if we are in split-screen windowing mode and both halves of
                 // the screen are opaque.
-                return false;
+                return STACK_VISIBILITY_INVISIBLE;
             }
             if (isAssistantType && gotSplitScreenStack) {
                 // Assistant stack can't be visible behind split-screen. In addition to this not
                 // making sense, it also works around an issue here we boost the z-order of the
                 // assistant window surfaces in window manager whenever it is visible.
-                return false;
+                return STACK_VISIBILITY_INVISIBLE;
             }
         }
 
-        // Well, nothing is stopping you from being visible...
-        return true;
+        if (!shouldBeVisible) {
+            return STACK_VISIBILITY_INVISIBLE;
+        }
+
+        // Handle cases when there can be a translucent split-screen stack on top.
+        switch (windowingMode) {
+            case WINDOWING_MODE_FULLSCREEN:
+                if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
+                    // At least one of the split-screen stacks that covers this one is translucent.
+                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+                }
+                break;
+            case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+                if (gotTranslucentSplitScreenPrimary) {
+                    // Covered by translucent primary split-screen on top.
+                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+                }
+                break;
+            case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
+                if (gotTranslucentSplitScreenSecondary) {
+                    // Covered by translucent secondary split-screen on top.
+                    return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
+                }
+                break;
+        }
+
+        // Lastly - check if there is a translucent fullscreen stack on top.
+        return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
+                : STACK_VISIBILITY_VISIBLE;
     }
 
     final int rankTaskLayers(int baseLayer) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7aa3481..875fc4e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1383,6 +1383,7 @@
                 .setProfilerInfo(profilerInfo)
                 .setActivityOptions(bOptions)
                 .setMayWait(userId)
+                .setAllowBackgroundActivityStart(true)
                 .execute();
     }
 
@@ -1398,6 +1399,7 @@
                 .setResolvedType(resolvedType)
                 .setActivityOptions(bOptions)
                 .setMayWait(userId)
+                .setAllowBackgroundActivityStart(true)
                 .execute();
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 928b57c..5cfc20b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -23,7 +23,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -38,6 +37,7 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.GONE;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
@@ -138,6 +138,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -172,6 +173,7 @@
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
@@ -3251,6 +3253,36 @@
         mInputMethodTargetWaitingAnim = targetWaitingAnim;
         assignWindowLayers(false /* setLayoutNeeded */);
         mInsetsStateController.onImeTargetChanged(target);
+        updateImeParent();
+    }
+
+    private void updateImeParent() {
+        if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE) {
+            return;
+        }
+        final SurfaceControl newParent = computeImeParent();
+        if (newParent != null) {
+            mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+            scheduleAnimation();
+        }
+    }
+
+    /**
+     * Computes the window the IME should be attached to.
+     */
+    @VisibleForTesting
+    SurfaceControl computeImeParent() {
+
+        // Attach it to app if the target is part of an app and such app is covering the entire
+        // screen. If it's not covering the entire screen the IME might extend beyond the apps
+        // bounds.
+        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null &&
+                mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+            return mInputMethodTarget.mAppToken.getSurfaceControl();
+        }
+
+        // Otherwise, we just attach it to the display.
+        return mWindowingLayer;
     }
 
     boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
@@ -4885,6 +4917,11 @@
                 .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
     }
 
+    @VisibleForTesting
+    SurfaceControl getWindowingLayer() {
+        return mWindowingLayer;
+    }
+
     /**
      * Create a portal window handle for input. This window transports any touch to the display
      * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
@@ -4909,4 +4946,19 @@
         portalWindowHandle.portalToDisplayId = mDisplayId;
         return portalWindowHandle;
     }
+
+    /**
+     * @see IWindowManager#setForwardedInsets
+     */
+    public void setForwardedInsets(Insets insets) {
+        if (insets == null) {
+            insets = Insets.NONE;
+        }
+        if (mDisplayPolicy.getForwardedInsets().equals(insets)) {
+            return;
+        }
+        mDisplayPolicy.setForwardedInsets(insets);
+        setLayoutNeeded();
+        mWmService.mWindowPlacerLocked.requestTraversal();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index bbf115f..2ee30ac 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -27,6 +27,7 @@
 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.view.InsetsState.TYPE_TOP_BAR;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
@@ -103,6 +104,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.localLOGV;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
@@ -110,6 +112,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.hardware.power.V1_0.PowerHint;
@@ -134,6 +137,7 @@
 import android.view.PointerIcon;
 import android.view.Surface;
 import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerGlobal;
@@ -339,6 +343,16 @@
 
     private InputConsumer mInputConsumer = null;
 
+    /**
+     * The area covered by system windows which belong to another display. Forwarded insets is set
+     * in case this is a virtual display, this is displayed on another display that has insets, and
+     * the bounds of this display is overlapping with the insets of the host display (e.g. IME is
+     * displayed on the host display, and it covers a part of this virtual display.)
+     * The forwarded insets is used to compute display frames of this virtual display, which will
+     * be then used to layout windows in the virtual display.
+     */
+    @NonNull private Insets mForwardedInsets = Insets.NONE;
+
     // -------- PolicyHandler --------
     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
     private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
@@ -1362,6 +1376,15 @@
             displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top,
                     displayFrames.mStable.top);
         }
+
+        // In case this is a virtual display, and the host display has insets that overlap this
+        // virtual display, apply the insets of the overlapped area onto the current and content
+        // frame of this virtual display. This let us layout windows in the virtual display as
+        // expected when the window needs to avoid overlap with the system windows.
+        // TODO: Generalize the forwarded insets, so that we can handle system windows other than
+        // IME.
+        displayFrames.mCurrent.inset(mForwardedInsets);
+        displayFrames.mContent.inset(mForwardedInsets);
     }
 
     private void layoutScreenDecorWindows(DisplayFrames displayFrames) {
@@ -1900,7 +1923,10 @@
                         if (win.isVoiceInteraction()) {
                             cf.set(displayFrames.mVoiceContent);
                         } else {
-                            if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
+                            // IME Insets are handled on the client for ADJUST_RESIZE in the new
+                            // insets world
+                            if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
+                                    || adjust != SOFT_INPUT_ADJUST_RESIZE) {
                                 cf.set(displayFrames.mDock);
                             } else {
                                 cf.set(displayFrames.mContent);
@@ -1991,7 +2017,11 @@
                     of.set(displayFrames.mRestricted);
                     df.set(displayFrames.mRestricted);
                     pf.set(displayFrames.mRestricted);
-                    if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
+
+                    // IME Insets are handled on the client for ADJUST_RESIZE in the new insets
+                    // world
+                    if (ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_NONE
+                            || adjust != SOFT_INPUT_ADJUST_RESIZE) {
                         cf.set(displayFrames.mDock);
                     } else {
                         cf.set(displayFrames.mContent);
@@ -2718,6 +2748,18 @@
         }
     }
 
+    /**
+     * @see IWindowManager#setForwardedInsets
+     */
+    public void setForwardedInsets(@NonNull Insets forwardedInsets) {
+        mForwardedInsets = forwardedInsets;
+    }
+
+    @NonNull
+    public Insets getForwardedInsets() {
+        return mForwardedInsets;
+    }
+
     @NavigationBarPosition
     int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
         if (navigationBarCanMove() && displayWidth > displayHeight) {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index afae9c4..a1b52f4 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -112,6 +112,7 @@
      * Called when a layout pass has occurred.
      */
     void onPostLayout() {
+        mState.setDisplayFrame(mDisplayContent.getBounds());
         for (int i = mControllers.size() - 1; i>= 0; i--) {
             mControllers.valueAt(i).onPostLayout();
         }
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
index bbe5424..b2e8bbe 100644
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -1,34 +1,4 @@
 {
-  "presubmit": [
-    {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.wm."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
-    },
-    {
-      "name": "WmTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.wm."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
-    }
-  ],
   "postsubmit": [
     {
       "name": "CtsWindowManagerDeviceTestCases"
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3bb6608..6c3e1f4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -134,6 +134,7 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
+import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -6438,6 +6439,23 @@
         }
     }
 
+    @Override
+    public void setForwardedInsets(int displayId, Insets insets) throws RemoteException {
+        synchronized (mGlobalLock) {
+            final DisplayContent dc = mRoot.getDisplayContent(displayId);
+            if (dc == null) {
+                return;
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int displayOwnerUid = dc.getDisplay().getOwnerUid();
+            if (callingUid != displayOwnerUid) {
+                throw new SecurityException(
+                        "Only owner of the display can set ForwardedInsets to it.");
+            }
+            dc.setForwardedInsets(insets);
+        }
+    }
+
     void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
         mTmpRect3.set(display);
         mTmpRect3.inset(insets);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 33317b5..c18e98b 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -373,6 +373,9 @@
     mInputManager->getReader()->dump(dump);
     dump += "\n";
 
+    mInputManager->getClassifier()->dump(dump);
+    dump += "\n";
+
     mInputManager->getDispatcher()->dump(dump);
     dump += "\n";
 }
diff --git a/services/core/jni/com_android_server_security_VerityUtils.cpp b/services/core/jni/com_android_server_security_VerityUtils.cpp
index bf96f9a..6cd9f2c 100644
--- a/services/core/jni/com_android_server_security_VerityUtils.cpp
+++ b/services/core/jni/com_android_server_security_VerityUtils.cpp
@@ -122,7 +122,7 @@
     }
 
     ~JavaByteArrayHolder() {
-        LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released");
+        LOG_ALWAYS_FATAL_IF(mElements != nullptr, "Elements are not released");
     }
 
   private:
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1155f49..e30acf7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12790,10 +12790,6 @@
         }
     }
 
-    // TODO(b/22388012): When backup is available for secondary users and profiles, consider
-    // whether there are any privacy/security implications of enabling the backup service here
-    // if there are other users or profiles unmanaged or managed by a different entity (i.e. not
-    // affiliated).
     @Override
     public void setBackupServiceEnabled(ComponentName admin, boolean enabled) {
         if (!mHasFeature) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ab30cda..a6017f2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -64,6 +64,7 @@
 import android.util.Slog;
 import android.util.TimingsTraceLog;
 import android.view.WindowManager;
+import android.view.contentcapture.ContentCaptureManager;
 import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
@@ -2214,33 +2215,30 @@
     }
 
     private void startContentCaptureService(@NonNull Context context) {
-        // Check if it was explicitly enabled by DeviceConfig
-        final String settings = DeviceConfig.getProperty(DeviceConfig.ContentCapture.NAMESPACE,
-                DeviceConfig.ContentCapture.PROPERTY_CONTENTCAPTURE_ENABLED);
-        if (settings == null) {
-            // Better be safe than sorry...
-            Slog.d(TAG, "ContentCaptureService disabled because its not set by OEM");
-            return;
-        }
-        switch (settings) {
-            case "always":
-                // Should be used only during development
+        // First check if it was explicitly enabled by DeviceConfig
+        boolean explicitlySupported = false;
+        String settings = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+                ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
+        if (settings != null && !settings.equalsIgnoreCase("default")) {
+            explicitlySupported = Boolean.parseBoolean(settings);
+            if (explicitlySupported) {
                 Slog.d(TAG, "ContentCaptureService explicitly enabled by DeviceConfig");
-                break;
-            case "default":
-                // Default case: check if OEM overlaid the resource that defines the service.
-                final String serviceName = context.getString(
-                        com.android.internal.R.string.config_defaultContentCaptureService);
-                if (TextUtils.isEmpty(serviceName)) {
-                    Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
-                    return;
-                }
-                break;
-            default:
-                // Kill switch for OEMs
-                Slog.d(TAG, "ContentCaptureService disabled because its set to: " + settings);
+            } else {
+                Slog.d(TAG, "ContentCaptureService explicitly disabled by DeviceConfig");
                 return;
+            }
         }
+
+        // Then check if OEM overlaid the resource that defines the service.
+        if (!explicitlySupported) {
+            final String serviceName = context
+                    .getString(com.android.internal.R.string.config_defaultContentCaptureService);
+            if (TextUtils.isEmpty(serviceName)) {
+                Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
+                return;
+            }
+        }
+
         traceBeginAndSlog("StartContentCaptureService");
         mSystemServiceManager.startService(CONTENT_CAPTURE_MANAGER_SERVICE_CLASS);
         traceEnd();
diff --git a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
index 2f8e545..63015be6 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppCompactorTest.java
@@ -147,10 +147,10 @@
                 KEY_USE_COMPACTION, "true", false);
         DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                 KEY_COMPACT_ACTION_1,
-                Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 3) + 1), false);
+                Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1), false);
         DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                 KEY_COMPACT_ACTION_2,
-                Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 3) + 1), false);
+                Integer.toString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1), false);
         DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                 KEY_COMPACT_THROTTLE_1,
                 Long.toString(AppCompactor.DEFAULT_COMPACT_THROTTLE_1 + 1), false);
@@ -173,9 +173,9 @@
         assertThat(mCompactorUnderTest.mCompactionThread.isAlive(), is(true));
 
         assertThat(mCompactorUnderTest.mCompactActionSome,
-                is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 3) + 1)));
+                is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1)));
         assertThat(mCompactorUnderTest.mCompactActionFull,
-                is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 3) + 1)));
+                is(compactActionIntToString((AppCompactor.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1)));
         assertThat(mCompactorUnderTest.mCompactThrottleSomeSome,
                 is(AppCompactor.DEFAULT_COMPACT_THROTTLE_1 + 1));
         assertThat(mCompactorUnderTest.mCompactThrottleSomeFull,
@@ -233,13 +233,13 @@
 
         // When we override new values for the compaction action with reasonable values...
 
-        // There are three possible values for compactAction[Some|Full].
-        for (int i = 1; i < 4; i++) {
+        // There are four possible values for compactAction[Some|Full].
+        for (int i = 1; i < 5; i++) {
             mCountDown = new CountDownLatch(2);
-            int expectedSome = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_1 + i) % 3 + 1;
+            int expectedSome = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_1 + i) % 4 + 1;
             DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                     KEY_COMPACT_ACTION_1, Integer.toString(expectedSome), false);
-            int expectedFull = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_2 + i) % 3 + 1;
+            int expectedFull = (mCompactorUnderTest.DEFAULT_COMPACT_ACTION_2 + i) % 4 + 1;
             DeviceConfig.setProperty(DeviceConfig.ActivityManager.NAMESPACE,
                     KEY_COMPACT_ACTION_2, Integer.toString(expectedFull), false);
             assertThat(mCountDown.await(5, TimeUnit.SECONDS), is(true));
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 192915f..4073ff1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -24,6 +24,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
@@ -34,6 +35,9 @@
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
+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 org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -381,6 +385,21 @@
     }
 
     @Test
+    public void testShouldResume_stackVisibility() {
+        mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
+        spyOn(mStack);
+
+        doReturn(STACK_VISIBILITY_VISIBLE).when(mStack).getVisibility(null);
+        assertEquals(true, mActivity.shouldResumeActivity(null /* activeActivity */));
+
+        doReturn(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT).when(mStack).getVisibility(null);
+        assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));
+
+        doReturn(STACK_VISIBILITY_INVISIBLE).when(mStack).getVisibility(null);
+        assertEquals(false, mActivity.shouldResumeActivity(null /* activeActivity */));
+    }
+
+    @Test
     public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
         mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 986943a..822700f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -37,6 +37,9 @@
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+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.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 
@@ -321,12 +324,23 @@
         assertFalse(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenPrimary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenSecondary.getVisibility(null /* starting */));
 
         // Home stack should be visible if one of the halves of split-screen is translucent.
         splitScreenPrimary.setIsTranslucent(true);
         assertTrue(homeStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                homeStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenPrimary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenSecondary.getVisibility(null /* starting */));
 
         final TestActivityStack splitScreenSecondary2 =
                 createStackForShouldBeVisibleTest(mDefaultDisplay,
@@ -336,12 +350,20 @@
         splitScreenSecondary2.setIsTranslucent(false);
         assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                splitScreenSecondary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenSecondary2.getVisibility(null /* starting */));
 
         // First split-screen secondary should be visible behind another translucent split-screen
         // secondary.
         splitScreenSecondary2.setIsTranslucent(true);
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                splitScreenSecondary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenSecondary2.getVisibility(null /* starting */));
 
         final TestActivityStack assistantStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
@@ -352,6 +374,14 @@
         assertFalse(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertFalse(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertFalse(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                assistantStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                splitScreenPrimary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                splitScreenSecondary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                splitScreenSecondary2.getVisibility(null /* starting */));
 
         // Split-screen stacks should be visible behind a translucent fullscreen stack.
         assistantStack.setIsTranslucent(true);
@@ -359,6 +389,14 @@
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                assistantStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                splitScreenPrimary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                splitScreenSecondary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                splitScreenSecondary2.getVisibility(null /* starting */));
 
         // Assistant stack shouldn't be visible behind translucent split-screen stack
         assistantStack.setIsTranslucent(false);
@@ -369,6 +407,113 @@
         assertFalse(assistantStack.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenPrimary.shouldBeVisible(null /* starting */));
         assertTrue(splitScreenSecondary2.shouldBeVisible(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                assistantStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenPrimary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                splitScreenSecondary.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                splitScreenSecondary2.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenBehindTranslucent() {
+        final TestActivityStack bottomStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+        final TestActivityStack translucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                bottomStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                translucentStack.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenBehindTranslucentAndOpaque() {
+        final TestActivityStack bottomStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+        final TestActivityStack translucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+        final TestActivityStack opaqueStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+
+        assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                translucentStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenBehindOpaqueAndTranslucent() {
+        final TestActivityStack bottomStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+        final TestActivityStack opaqueStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+        final TestActivityStack translucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+
+        assertEquals(STACK_VISIBILITY_INVISIBLE, bottomStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                opaqueStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                translucentStack.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenTranslucentBehindTranslucent() {
+        final TestActivityStack bottomTranslucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+        final TestActivityStack translucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                bottomTranslucentStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                translucentStack.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenTranslucentBehindOpaque() {
+        final TestActivityStack bottomTranslucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+        final TestActivityStack opaqueStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+
+        assertEquals(STACK_VISIBILITY_INVISIBLE,
+                bottomTranslucentStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE, opaqueStack.getVisibility(null /* starting */));
+    }
+
+    @Test
+    public void testGetVisibility_FullscreenBehindTranslucentAndPip() {
+        final TestActivityStack bottomStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        false /* translucent */);
+        final TestActivityStack translucentStack =
+                createStandardStackForVisibilityTest(WINDOWING_MODE_FULLSCREEN,
+                        true /* translucent */);
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+
+        assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                bottomStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE,
+                translucentStack.getVisibility(null /* starting */));
+        assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
     }
 
     @Test
@@ -628,6 +773,14 @@
         assertFalse(assistantStack.shouldBeVisible(null /* starting */));
     }
 
+    private TestActivityStack createStandardStackForVisibilityTest(int windowingMode,
+            boolean translucent) {
+        final TestActivityStack stack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+                windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        stack.setIsTranslucent(translucent);
+        return stack;
+    }
+
     @SuppressWarnings("TypeParameterUnusedInFormals")
     private <T extends ActivityStack> T createStackForShouldBeVisibleTest(
             ActivityDisplay display, int windowingMode, int activityType, boolean onTop) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3826fac..a62bc71 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -51,17 +51,22 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 
 import android.annotation.SuppressLint;
+import android.app.WindowConfiguration;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
 import android.util.DisplayMetrics;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.ViewRootImpl;
+import android.view.test.InsetsModeSession;
 
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
@@ -628,6 +633,39 @@
                 eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
     }
 
+    @Test
+    public void testComputeImeParent_app() throws Exception {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+            final DisplayContent dc = createNewDisplay();
+            dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
+            assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
+                    dc.computeImeParent());
+        }
+    }
+
+    @Test
+    public void testComputeImeParent_app_notFullscreen() throws Exception {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+            final DisplayContent dc = createNewDisplay();
+            dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
+            dc.mInputMethodTarget.setWindowingMode(
+                    WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+            assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+        }
+    }
+
+    @Test
+    public void testComputeImeParent_noApp() throws Exception {
+        try (final InsetsModeSession session =
+                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+            final DisplayContent dc = createNewDisplay();
+            dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
+            assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+        }
+    }
+
     private boolean isOptionsPanelAtRight(int displayId) {
         return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 845a09f..4279c41 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -28,6 +28,8 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
@@ -37,6 +39,7 @@
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 
+import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
@@ -350,6 +353,48 @@
     }
 
     @Test
+    public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() {
+        synchronized (mWm.mGlobalLock) {
+            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+            addWindow(mWindow);
+
+            final int forwardedInsetBottom = 50;
+            mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
+            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+            assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0);
+            assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+            assertInsetByTopBottom(mWindow.getContentFrameLw(),
+                    STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
+            assertInsetByTopBottom(mWindow.getVisibleFrameLw(),
+                    STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT + forwardedInsetBottom);
+            assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0);
+            assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
+        }
+    }
+
+    @Test
+    public void layoutWindowLw_withForwardInset_SoftInputAdjustNothing() {
+        synchronized (mWm.mGlobalLock) {
+            mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
+            addWindow(mWindow);
+
+            final int forwardedInsetBottom = 50;
+            mDisplayPolicy.setForwardedInsets(Insets.of(0, 0, 0, forwardedInsetBottom));
+            mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+            mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+            assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0);
+            assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+            assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+            assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+            assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0);
+            assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
+        }
+    }
+
+    @Test
     public void layoutHint_appWindow() {
         synchronized (mWm.mGlobalLock) {
             // Initialize DisplayFrames
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8876214..3eb9085 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -39,6 +39,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static org.hamcrest.Matchers.is;
@@ -53,6 +54,7 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
 
 import android.graphics.Insets;
 import android.graphics.Matrix;
@@ -65,11 +67,13 @@
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import org.junit.AfterClass;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -88,6 +92,7 @@
 
     @BeforeClass
     public static void setUpOnce() {
+        // TODO: Make use of SettingsSession when it becomes feasible for this.
         sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode;
         // To let the insets provider control the insets visibility, the insets mode has to be
         // NEW_INSETS_MODE_FULL.
@@ -99,6 +104,15 @@
         ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode;
     }
 
+    @Before
+    public void setUp() {
+        // TODO: Let the insets source with new mode keep the visibility control, and remove this
+        // setup code. Now mTopFullscreenOpaqueWindowState will take back the control of insets
+        // visibility.
+        spyOn(mDisplayContent);
+        doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
+    }
+
     @Test
     public void testIsParentWindowHidden() {
         final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -345,6 +359,7 @@
         assertFalse(app.canAffectSystemUiFlags());
     }
 
+    @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
     @Test
     public void testVisibleWithInsetsProvider() throws Exception {
         final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar");
@@ -356,6 +371,7 @@
         mDisplayContent.getInsetsStateController().onBarControllingWindowChanged(app);
         mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
                 .onInsetsModified(app, new InsetsSource(TYPE_TOP_BAR));
+        waitUntilHandlersIdle();
         assertFalse(topBar.isVisible());
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 7cab432..93f758c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1307,13 +1307,15 @@
 
                 List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user);
 
+                int userId = user.getIdentifier();
                 if (roleHolders.isEmpty()) {
-                    Settings.Secure.putString(getContext().getContentResolver(),
-                            Settings.Secure.ASSISTANT, "");
-                    Settings.Secure.putString(getContext().getContentResolver(),
-                            Settings.Secure.VOICE_INTERACTION_SERVICE, "");
-                    Settings.Secure.putString(getContext().getContentResolver(),
-                            Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user));
+                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                            Settings.Secure.ASSISTANT, "", userId);
+                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                            Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
+                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                            Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user),
+                            userId);
                 } else {
                     // Assistant is singleton role
                     String pkg = roleHolders.get(0);
@@ -1321,7 +1323,7 @@
                     // Try to set role holder as VoiceInteractionService
                     List<ResolveInfo> services = mPm.queryIntentServicesAsUser(
                             new Intent(VoiceInteractionService.SERVICE_INTERFACE).setPackage(pkg),
-                            PackageManager.GET_META_DATA, user.getIdentifier());
+                            PackageManager.GET_META_DATA, userId);
 
                     for (ResolveInfo resolveInfo : services) {
                         ServiceInfo serviceInfo = resolveInfo.serviceInfo;
@@ -1339,12 +1341,14 @@
                                 voiceInteractionServiceInfo.getRecognitionService())
                                 .flattenToShortString();
 
-                        Settings.Secure.putString(getContext().getContentResolver(),
-                                Settings.Secure.ASSISTANT, serviceComponentName);
-                        Settings.Secure.putString(getContext().getContentResolver(),
-                                Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName);
-                        Settings.Secure.putString(getContext().getContentResolver(),
-                                Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName);
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                                Settings.Secure.ASSISTANT, serviceComponentName, userId);
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                                Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName,
+                                userId);
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                                Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName,
+                                userId);
 
                         return;
                     }
@@ -1352,19 +1356,19 @@
                     // If no service could be found try to set assist activity
                     final List<ResolveInfo> activities = mPm.queryIntentActivitiesAsUser(
                             new Intent(Intent.ACTION_ASSIST).setPackage(pkg),
-                            PackageManager.MATCH_DEFAULT_ONLY, user.getIdentifier());
+                            PackageManager.MATCH_DEFAULT_ONLY, userId);
 
                     for (ResolveInfo resolveInfo : activities) {
                         ActivityInfo activityInfo = resolveInfo.activityInfo;
 
-                        Settings.Secure.putString(getContext().getContentResolver(),
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                 Settings.Secure.ASSISTANT,
-                                activityInfo.getComponentName().flattenToShortString());
-                        Settings.Secure.putString(getContext().getContentResolver(),
-                                Settings.Secure.VOICE_INTERACTION_SERVICE, "");
-                        Settings.Secure.putString(getContext().getContentResolver(),
+                                activityInfo.getComponentName().flattenToShortString(), userId);
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
+                                Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
+                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                 Settings.Secure.VOICE_RECOGNITION_SERVICE,
-                                getDefaultRecognizer(user));
+                                getDefaultRecognizer(user), userId);
                     }
                 }
             }
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 818ebd9..2fa388f 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -75,7 +75,7 @@
  *
  * public void requestRole() {
  *     RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
- *     Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING_APP");
+ *     Intent intent = roleManager.createRequestRoleIntent("android.app.role.CALL_SCREENING");
  *     startActivityForResult(intent, REQUEST_ID);
  * }
  *
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index f5f0af7..cbcd40f 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -35,7 +35,6 @@
 import com.android.internal.telecom.IInCallAdapter;
 import com.android.internal.telecom.IInCallService;
 
-import java.lang.String;
 import java.util.Collections;
 import java.util.List;
 
@@ -212,7 +211,7 @@
  *     {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
  * </ul>
  * <p>
- * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER_APP} in order to
+ * Your app should request to fill the role {@code android.app.role.CAR_MODE_DIALER} in order to
  * become the default (see <a href="#requestRole">above</a> for how to request your app fills this
  * role).
  *
@@ -232,7 +231,7 @@
  *     {@link android.Manifest.permission.CALL_COMPANION_APP}.</li>
  * </ul>
  * <p>
- * Your app should request to fill the role {@code android.app.role.CALL_COMPANION_APP} in order to
+ * Your app should request to fill the role {@code android.app.role.CALL_COMPANION} in order to
  * become a call companion app (see <a href="#requestRole">above</a> for how to request your app
  * fills this role).
  */
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 30e641d..a4207c9 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -63,6 +63,10 @@
     public CellSignalStrengthGsm(android.hardware.radio.V1_0.GsmSignalStrength gsm) {
         // Convert from HAL values as part of construction.
         this(getRssiDbmFromAsu(gsm.signalStrength), gsm.bitErrorRate, gsm.timingAdvance);
+
+        if (mRssi == CellInfo.UNAVAILABLE) {
+            setDefaultValues();
+        }
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index 6f52b85..5ae89b0 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -72,6 +72,10 @@
         // Convert from HAL values as part of construction.
         this(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
                 tdscdma.rscp != CellInfo.UNAVAILABLE ? -tdscdma.rscp : tdscdma.rscp);
+
+        if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+            setDefaultValues();
+        }
     }
 
     /** @hide */
@@ -79,6 +83,10 @@
         // Convert from HAL values as part of construction.
         this(getRssiDbmFromAsu(tdscdma.signalStrength),
                 tdscdma.bitErrorRate, getRscpDbmFromAsu(tdscdma.rscp));
+
+        if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+            setDefaultValues();
+        }
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 0760407..efa3647 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -92,8 +92,12 @@
     /** @hide */
     public CellSignalStrengthWcdma(android.hardware.radio.V1_0.WcdmaSignalStrength wcdma) {
         // Convert from HAL values as part of construction.
-        this(getRssiDbmFromAsu(wcdma.signalStrength),
-                wcdma.bitErrorRate, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
+        this(getRssiDbmFromAsu(wcdma.signalStrength), wcdma.bitErrorRate,
+                CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
+
+        if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+            setDefaultValues();
+        }
     }
 
     /** @hide */
@@ -103,6 +107,10 @@
                     wcdma.base.bitErrorRate,
                     getRscpDbmFromAsu(wcdma.rscp),
                     getEcNoDbFromAsu(wcdma.ecno));
+
+        if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
+            setDefaultValues();
+        }
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index e40bae1..099015f 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -187,15 +187,7 @@
         int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
         String format = (PHONE_TYPE_CDMA == activePhone) ?
                 SmsConstants.FORMAT_3GPP2 : SmsConstants.FORMAT_3GPP;
-        message = createFromPdu(pdu, format);
-
-        if (null == message || null == message.mWrappedSmsMessage) {
-            // decoding pdu failed based on activePhone type, must be other format
-            format = (PHONE_TYPE_CDMA == activePhone) ?
-                    SmsConstants.FORMAT_3GPP : SmsConstants.FORMAT_3GPP2;
-            message = createFromPdu(pdu, format);
-        }
-        return message;
+        return createFromPdu(pdu, format);
     }
 
     /**
@@ -211,11 +203,18 @@
      * {@link android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION} intent
      */
     public static SmsMessage createFromPdu(byte[] pdu, String format) {
-        SmsMessageBase wrappedMessage;
+        return createFromPdu(pdu, format, true);
+    }
+
+    private static SmsMessage createFromPdu(byte[] pdu, String format,
+            boolean fallbackToOtherFormat) {
         if (pdu == null) {
             Rlog.i(LOG_TAG, "createFromPdu(): pdu is null");
             return null;
         }
+        SmsMessageBase wrappedMessage;
+        String otherFormat = SmsConstants.FORMAT_3GPP2.equals(format) ? SmsConstants.FORMAT_3GPP :
+                SmsConstants.FORMAT_3GPP2;
         if (SmsConstants.FORMAT_3GPP2.equals(format)) {
             wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
         } else if (SmsConstants.FORMAT_3GPP.equals(format)) {
@@ -228,8 +227,12 @@
         if (wrappedMessage != null) {
             return new SmsMessage(wrappedMessage);
         } else {
-            Rlog.e(LOG_TAG, "createFromPdu(): wrappedMessage is null");
-            return null;
+            if (fallbackToOtherFormat) {
+                return createFromPdu(pdu, otherFormat, false);
+            } else {
+                Rlog.e(LOG_TAG, "createFromPdu(): wrappedMessage is null");
+                return null;
+            }
         }
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index dfe36ef..313146d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2047,6 +2047,8 @@
             putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
+            intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+            intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index eab536f..f5d452e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4920,12 +4920,13 @@
      *
      * <p>Apps targeting {@link android.os.Build.VERSION_CODES#Q Android Q} or higher will no
      * longer trigger a refresh of the cached CellInfo by invoking this API. Instead, those apps
-     * will receive the latest cached results. Apps targeting
+     * will receive the latest cached results, which may not be current. Apps targeting
      * {@link android.os.Build.VERSION_CODES#Q Android Q} or higher that wish to request updated
      * CellInfo should call
-     * {android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()} and
-     * listen for responses via {@link android.telephony.PhoneStateListener#onCellInfoChanged
-     * onCellInfoChanged()}.
+     * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()};
+     * however, in all cases, updates will be rate-limited and are not guaranteed. To determine the
+     * recency of CellInfo data, callers should check
+     * {@link android.telephony.CellInfo#getTimeStamp CellInfo#getTimeStamp()}.
      *
      * <p>This method returns valid data for devices with
      * {@link android.content.pm.PackageManager#FEATURE_TELEPHONY FEATURE_TELEPHONY}. In cases
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index cc28ee0..3255f8d 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -23,7 +23,7 @@
  * {@link RcsParticipant}s. Please see Section 5 (1-to-1 Messaging) - GSMA RCC.71 (RCS Universal
  * Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class Rcs1To1Thread extends RcsThread {
     private int mThreadId;
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 744ac76..ef359a1 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -16,14 +16,17 @@
 package android.telephony.ims;
 
 import android.os.Parcel;
-import android.os.Parcelable;
 
 /**
  * The base class for events that can happen on {@link RcsParticipant}s and {@link RcsThread}s.
- * @hide - TODO(109759350) make this public
+ *
+ * @hide - TODO: make public
  */
-public abstract class RcsEvent implements Parcelable {
-    protected long mTimestamp;
+public abstract class RcsEvent {
+    /**
+     * @hide
+     */
+    protected final long mTimestamp;
 
     protected RcsEvent(long timestamp) {
         mTimestamp = timestamp;
@@ -44,17 +47,17 @@
      */
     abstract void persist() throws RcsMessageStoreException;
 
+    /**
+     * @hide
+     */
     RcsEvent(Parcel in) {
         mTimestamp = in.readLong();
     }
 
-    @Override
+    /**
+     * @hide
+     */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(mTimestamp);
     }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
 }
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl
deleted file mode 100644
index 9a3600b..0000000
--- a/telephony/java/android/telephony/ims/RcsEventQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsEventQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
index 52e73ce..f18c4df 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsEventQueryParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsEventQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParameters.java b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
similarity index 83%
rename from telephony/java/android/telephony/ims/RcsEventQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsEventQueryParams.java
index 6aee56f..5249bec 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
@@ -35,29 +35,29 @@
 
 /**
  * The parameters to pass into
- * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} in order to select a
  * subset of {@link RcsEvent}s present in the message store.
  *
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
  */
-public class RcsEventQueryParameters implements Parcelable {
+public final class RcsEventQueryParams implements Parcelable {
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return all types of
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return all types of
      * {@link RcsEvent}s
      */
     public static final int ALL_EVENTS = -1;
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return sub-types of
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return sub-types of
      * {@link RcsGroupThreadEvent}s
      */
     public static final int ALL_GROUP_THREAD_EVENTS = 0;
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
      * {@link RcsParticipantAliasChangedEvent}s
      */
     public static final int PARTICIPANT_ALIAS_CHANGED_EVENT =
@@ -65,7 +65,7 @@
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
      * {@link RcsGroupThreadParticipantJoinedEvent}s
      */
     public static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT =
@@ -73,7 +73,7 @@
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
      * {@link RcsGroupThreadParticipantLeftEvent}s
      */
     public static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT =
@@ -81,14 +81,14 @@
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
      * {@link RcsGroupThreadNameChangedEvent}s
      */
     public static final int GROUP_THREAD_NAME_CHANGED_EVENT = NAME_CHANGED_EVENT_TYPE;
 
     /**
      * Flag to be used with {@link Builder#setEventType(int)} to make
-     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)} return only
+     * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} return only
      * {@link RcsGroupThreadIconChangedEvent}s
      */
     public static final int GROUP_THREAD_ICON_CHANGED_EVENT = ICON_CHANGED_EVENT_TYPE;
@@ -134,7 +134,7 @@
     // The thread that the results are limited to
     private int mThreadId;
 
-    RcsEventQueryParameters(@EventType int eventType, int threadId,
+    RcsEventQueryParams(@EventType int eventType, int threadId,
             @SortingProperty int sortingProperty, boolean isAscending, int limit) {
         mEventType = eventType;
         mSortingProperty = sortingProperty;
@@ -144,7 +144,7 @@
     }
 
     /**
-     * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParameters} is
+     * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParams} is
      * set to query for.
      */
     public @EventType int getEventType() {
@@ -152,7 +152,7 @@
     }
 
     /**
-     * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParameters} is
+     * @return Returns the type of {@link RcsEvent}s that this {@link RcsEventQueryParams} is
      * set to query for.
      */
     public int getLimit() {
@@ -186,7 +186,7 @@
     }
 
     /**
-     * A helper class to build the {@link RcsEventQueryParameters}.
+     * A helper class to build the {@link RcsEventQueryParams}.
      */
     public static class Builder {
         private @EventType int mEventType;
@@ -196,8 +196,8 @@
         private int mThreadId;
 
         /**
-         * Creates a new builder for {@link RcsEventQueryParameters} to be used in
-         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+         * Creates a new builder for {@link RcsEventQueryParams} to be used in
+         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
          */
         public Builder() {
             // empty implementation
@@ -236,7 +236,7 @@
 
         /**
          * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsEventQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+         * {@link RcsEventQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
          *
          * @param sortingProperty against which property the results should be sorted
          * @return The same instance of the builder to chain parameters.
@@ -273,18 +273,18 @@
         }
 
         /**
-         * Builds the {@link RcsEventQueryParameters} to use in
-         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+         * Builds the {@link RcsEventQueryParams} to use in
+         * {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
          *
-         * @return An instance of {@link RcsEventQueryParameters} to use with the event query.
+         * @return An instance of {@link RcsEventQueryParams} to use with the event query.
          */
-        public RcsEventQueryParameters build() {
-            return new RcsEventQueryParameters(mEventType, mThreadId, mSortingProperty,
+        public RcsEventQueryParams build() {
+            return new RcsEventQueryParams(mEventType, mThreadId, mSortingProperty,
                     mIsAscending, mLimit);
         }
     }
 
-    protected RcsEventQueryParameters(Parcel in) {
+    private RcsEventQueryParams(Parcel in) {
         mEventType = in.readInt();
         mThreadId = in.readInt();
         mSortingProperty = in.readInt();
@@ -292,20 +292,19 @@
         mLimit = in.readInt();
     }
 
-    public static final Creator<RcsEventQueryParameters> CREATOR =
-            new Creator<RcsEventQueryParameters>() {
+    public static final Creator<RcsEventQueryParams> CREATOR =
+            new Creator<RcsEventQueryParams>() {
                 @Override
-                public RcsEventQueryParameters createFromParcel(Parcel in) {
-                    return new RcsEventQueryParameters(in);
+                public RcsEventQueryParams createFromParcel(Parcel in) {
+                    return new RcsEventQueryParams(in);
                 }
 
                 @Override
-                public RcsEventQueryParameters[] newArray(int size) {
-                    return new RcsEventQueryParameters[size];
+                public RcsEventQueryParams[] newArray(int size) {
+                    return new RcsEventQueryParams[size];
                 }
             };
 
-
     @Override
     public int describeContents() {
         return 0;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.java b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
index 27898ab..f8d57fa 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
@@ -22,13 +22,13 @@
 import java.util.List;
 
 /**
- * The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
  * call. This class allows getting the token for querying the next batch of events in order to
  * prevent handling large amounts of data at once.
  *
- * @hide
+ * @hide - TODO: make public
  */
-public class RcsEventQueryResult implements Parcelable {
+public final class RcsEventQueryResult implements Parcelable {
     private RcsQueryContinuationToken mContinuationToken;
     private List<RcsEvent> mEvents;
 
@@ -63,7 +63,8 @@
         return mEvents;
     }
 
-    protected RcsEventQueryResult(Parcel in) {
+    private RcsEventQueryResult(Parcel in) {
+        mContinuationToken = in.readParcelable(RcsQueryContinuationToken.class.getClassLoader());
     }
 
     public static final Creator<RcsEventQueryResult> CREATOR = new Creator<RcsEventQueryResult>() {
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl
deleted file mode 100644
index 5fec021..0000000
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsFileTransferCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
index 52e73ce..1552190 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsFileTransferCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
similarity index 92%
rename from telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
index bd7cb4b..663def5 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
@@ -22,12 +22,12 @@
 
 /**
  * Pass an instance of this class to
- * {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParameters)} create an
+ * {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)} create an
  * {@link RcsFileTransferPart} and save it into storage.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsFileTransferCreationParameters implements Parcelable {
+public final class RcsFileTransferCreationParams implements Parcelable {
     private String mRcsFileTransferSessionId;
     private Uri mContentUri;
     private String mContentMimeType;
@@ -128,7 +128,7 @@
     /**
      * @hide
      */
-    RcsFileTransferCreationParameters(Builder builder) {
+    RcsFileTransferCreationParams(Builder builder) {
         mRcsFileTransferSessionId = builder.mRcsFileTransferSessionId;
         mContentUri = builder.mContentUri;
         mContentMimeType = builder.mContentMimeType;
@@ -143,7 +143,7 @@
     }
 
     /**
-     * A builder to create instances of {@link RcsFileTransferCreationParameters}
+     * A builder to create instances of {@link RcsFileTransferCreationParams}
      */
     public class Builder {
         private String mRcsFileTransferSessionId;
@@ -300,18 +300,18 @@
         }
 
         /**
-         * Creates an instance of {@link RcsFileTransferCreationParameters} with the given
+         * Creates an instance of {@link RcsFileTransferCreationParams} with the given
          * parameters.
          *
          * @return The same instance of {@link Builder} to chain methods
-         * @see RcsMessage#insertFileTransfer(RcsFileTransferCreationParameters)
+         * @see RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)
          */
-        public RcsFileTransferCreationParameters build() {
-            return new RcsFileTransferCreationParameters(this);
+        public RcsFileTransferCreationParams build() {
+            return new RcsFileTransferCreationParams(this);
         }
     }
 
-    protected RcsFileTransferCreationParameters(Parcel in) {
+    private RcsFileTransferCreationParams(Parcel in) {
         mRcsFileTransferSessionId = in.readString();
         mContentUri = in.readParcelable(Uri.class.getClassLoader());
         mContentMimeType = in.readString();
@@ -325,16 +325,16 @@
         mFileTransferStatus = in.readInt();
     }
 
-    public static final Creator<RcsFileTransferCreationParameters> CREATOR =
-            new Creator<RcsFileTransferCreationParameters>() {
+    public static final Creator<RcsFileTransferCreationParams> CREATOR =
+            new Creator<RcsFileTransferCreationParams>() {
                 @Override
-                public RcsFileTransferCreationParameters createFromParcel(Parcel in) {
-                    return new RcsFileTransferCreationParameters(in);
+                public RcsFileTransferCreationParams createFromParcel(Parcel in) {
+                    return new RcsFileTransferCreationParams(in);
                 }
 
                 @Override
-                public RcsFileTransferCreationParameters[] newArray(int size) {
-                    return new RcsFileTransferCreationParameters[size];
+                public RcsFileTransferCreationParams[] newArray(int size) {
+                    return new RcsFileTransferCreationParams[size];
                 }
             };
 
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 2eadc4a..1ce7999 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -27,7 +27,7 @@
  * A part of a composite {@link RcsMessage} that holds a file transfer. Please see Section 7
  * (File Transfer) - GSMA RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class RcsFileTransferPart {
     /**
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index 6f6258e..2c42494 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -30,7 +30,7 @@
  * or leave. Please see Section 6 (Group Chat) - GSMA RCC.71 (RCS Universal Profile Service
  * Definition Document)
  *
- * @hide - TODO(sahinc) make this public
+ * @hide - TODO: make public
  */
 public class RcsGroupThread extends RcsThread {
     /**
@@ -166,8 +166,8 @@
     @WorkerThread
     @NonNull
     public Set<RcsParticipant> getParticipants() throws RcsMessageStoreException {
-        RcsParticipantQueryParameters queryParameters =
-                new RcsParticipantQueryParameters.Builder().setThread(this).build();
+        RcsParticipantQueryParams queryParameters =
+                new RcsParticipantQueryParams.Builder().setThread(this).build();
 
         RcsParticipantQueryResult queryResult = RcsControllerCall.call(
                 iRcs -> iRcs.getParticipants(queryParameters));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index a18437b..bc61877 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -21,7 +21,7 @@
 /**
  * An event that happened on an {@link RcsGroupThread}.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public abstract class RcsGroupThreadEvent extends RcsEvent {
     private final int mRcsGroupThreadId;
@@ -50,13 +50,18 @@
         return new RcsParticipant(mOriginatingParticipantId);
     }
 
+    /**
+     * @hide
+     */
     RcsGroupThreadEvent(Parcel in) {
         super(in);
         mRcsGroupThreadId = in.readInt();
         mOriginatingParticipantId = in.readInt();
     }
 
-    @Override
+    /**
+     * @hide
+     */
     public void writeToParcel(Parcel dest, int flags) {
         super.writeToParcel(dest, flags);
         dest.writeInt(mRcsGroupThreadId);
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 7beed3b..74af973 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -19,14 +19,16 @@
 import android.annotation.Nullable;
 import android.net.Uri;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An event that indicates an {@link RcsGroupThread}'s icon was changed. Please see R6-2-5 - GSMA
  * RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent {
+public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent implements
+        Parcelable {
     private final Uri mNewIcon;
 
     /**
@@ -91,7 +93,7 @@
                 }
             };
 
-    protected RcsGroupThreadIconChangedEvent(Parcel in) {
+    private RcsGroupThreadIconChangedEvent(Parcel in) {
         super(in);
         mNewIcon = in.readParcelable(Uri.class.getClassLoader());
     }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 0d2ea4f..06f4d5b 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -18,15 +18,17 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An event that indicates an {@link RcsGroupThread}'s name was changed. Please see R6-2-5 - GSMA
  * RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent {
-    private String mNewName;
+public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent implements
+        Parcelable {
+    private final String mNewName;
 
     /**
      * Creates a new {@link RcsGroupThreadNameChangedEvent}. This event is not persisted into
@@ -89,7 +91,7 @@
                 }
             };
 
-    protected RcsGroupThreadNameChangedEvent(Parcel in) {
+    private RcsGroupThreadNameChangedEvent(Parcel in) {
         super(in);
         mNewName = in.readString();
     }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 2adafc7..4932707 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -17,15 +17,17 @@
 
 import android.annotation.NonNull;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An event that indicates an RCS participant has joined an {@link RcsThread}. Please see US6-3 -
  * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent {
-    private int mJoinedParticipantId;
+public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent implements
+        Parcelable {
+    private final int mJoinedParticipantId;
 
     /**
      * Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
@@ -89,7 +91,7 @@
                 }
             };
 
-    protected RcsGroupThreadParticipantJoinedEvent(Parcel in) {
+    private RcsGroupThreadParticipantJoinedEvent(Parcel in) {
         super(in);
         mJoinedParticipantId = in.readInt();
     }
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index 87c1852..970a046 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -17,15 +17,17 @@
 
 import android.annotation.NonNull;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An event that indicates an RCS participant has left an {@link RcsThread}. Please see US6-23 -
  * GSMA RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent {
-    private int mLeavingParticipantId;
+public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent implements
+        Parcelable {
+    private final int mLeavingParticipantId;
 
     /**
      * Creates a new {@link RcsGroupThreadParticipantLeftEvent}. his event is not persisted into
@@ -88,7 +90,7 @@
                 }
             };
 
-    protected RcsGroupThreadParticipantLeftEvent(Parcel in) {
+    private RcsGroupThreadParticipantLeftEvent(Parcel in) {
         super(in);
         mLeavingParticipantId = in.readInt();
     }
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 2ea115b..f3b7815 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -20,7 +20,7 @@
 /**
  * This is a single instance of a message received over RCS.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class RcsIncomingMessage extends RcsMessage {
     /**
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl
deleted file mode 100644
index 76073c2..0000000
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsIncomingMessageCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
index 52e73ce..1f1d4f6 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsIncomingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
similarity index 81%
rename from telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
index acde8af..64b2339 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
@@ -21,13 +21,13 @@
 import android.os.Parcelable;
 
 /**
- * {@link RcsIncomingMessageCreationParameters} is a collection of parameters that should be passed
- * into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)} to generate an
+ * {@link RcsIncomingMessageCreationParams} is a collection of parameters that should be passed
+ * into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} to generate an
  * {@link RcsIncomingMessage} on that {@link RcsThread}
  *
- * @hide TODO:make public
+ * @hide - TODO: make public
  */
-public class RcsIncomingMessageCreationParameters extends RcsMessageCreationParameters implements
+public final class RcsIncomingMessageCreationParams extends RcsMessageCreationParams implements
         Parcelable {
     // The arrival timestamp for the RcsIncomingMessage to be created
     private final long mArrivalTimestamp;
@@ -37,18 +37,18 @@
     private final int mSenderParticipantId;
 
     /**
-     * Builder to help create an {@link RcsIncomingMessageCreationParameters}
+     * Builder to help create an {@link RcsIncomingMessageCreationParams}
      *
-     * @see RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)
+     * @see RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)
      */
-    public static class Builder extends RcsMessageCreationParameters.Builder {
+    public static class Builder extends RcsMessageCreationParams.Builder {
         private RcsParticipant mSenderParticipant;
         private long mArrivalTimestamp;
         private long mSeenTimestamp;
 
         /**
          * Creates a {@link Builder} to create an instance of
-         * {@link RcsIncomingMessageCreationParameters}
+         * {@link RcsIncomingMessageCreationParams}
          *
          * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
          *                             timestamp value in milliseconds passed after midnight,
@@ -103,22 +103,22 @@
 
         /**
          * Creates parameters for creating a new incoming message.
-         * @return A new instance of {@link RcsIncomingMessageCreationParameters} to create a new
+         * @return A new instance of {@link RcsIncomingMessageCreationParams} to create a new
          * {@link RcsIncomingMessage}
          */
-        public RcsIncomingMessageCreationParameters build() {
-            return new RcsIncomingMessageCreationParameters(this);
+        public RcsIncomingMessageCreationParams build() {
+            return new RcsIncomingMessageCreationParams(this);
         }
     }
 
-    private RcsIncomingMessageCreationParameters(Builder builder) {
+    private RcsIncomingMessageCreationParams(Builder builder) {
         super(builder);
         mArrivalTimestamp = builder.mArrivalTimestamp;
         mSeenTimestamp = builder.mSeenTimestamp;
         mSenderParticipantId = builder.mSenderParticipant.getId();
     }
 
-    protected RcsIncomingMessageCreationParameters(Parcel in) {
+    private RcsIncomingMessageCreationParams(Parcel in) {
         super(in);
         mArrivalTimestamp = in.readLong();
         mSeenTimestamp = in.readLong();
@@ -152,16 +152,16 @@
         return mSenderParticipantId;
     }
 
-    public static final Creator<RcsIncomingMessageCreationParameters> CREATOR =
-            new Creator<RcsIncomingMessageCreationParameters>() {
+    public static final Creator<RcsIncomingMessageCreationParams> CREATOR =
+            new Creator<RcsIncomingMessageCreationParams>() {
                 @Override
-                public RcsIncomingMessageCreationParameters createFromParcel(Parcel in) {
-                    return new RcsIncomingMessageCreationParameters(in);
+                public RcsIncomingMessageCreationParams createFromParcel(Parcel in) {
+                    return new RcsIncomingMessageCreationParams(in);
                 }
 
                 @Override
-                public RcsIncomingMessageCreationParameters[] newArray(int size) {
-                    return new RcsIncomingMessageCreationParameters[size];
+                public RcsIncomingMessageCreationParams[] newArray(int size) {
+                    return new RcsIncomingMessageCreationParams[size];
                 }
             };
 
@@ -172,7 +172,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
+        super.writeToParcel(dest);
         dest.writeLong(mArrivalTimestamp);
         dest.writeLong(mSeenTimestamp);
         dest.writeInt(mSenderParticipantId);
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index e84d4ed..90bd044 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -20,11 +20,19 @@
 
 /**
  * The manager class for RCS related utilities.
- * @hide
+ *
+ * @hide - TODO: make public
  */
 @SystemService(Context.TELEPHONY_RCS_SERVICE)
 public class RcsManager {
 
+    /**
+     * @hide
+     */
+    public RcsManager() {
+        // empty constructor
+    }
+
     private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
 
     /**
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b70a9a7..1700941 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -28,7 +28,7 @@
 /**
  * This is a single instance of a message sent or received over RCS.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public abstract class RcsMessage {
     /**
@@ -83,7 +83,10 @@
      */
     public static final int SEEN = 9;
 
-    protected int mId;
+    /**
+     * @hide
+     */
+    protected final int mId;
 
     @IntDef({
             DRAFT, QUEUED, SENDING, SENT, RETRYING, FAILED, RECEIVED, SEEN
@@ -277,7 +280,7 @@
     @NonNull
     @WorkerThread
     public RcsFileTransferPart insertFileTransfer(
-            RcsFileTransferCreationParameters fileTransferCreationParameters)
+            RcsFileTransferCreationParams fileTransferCreationParameters)
             throws RcsMessageStoreException {
         return new RcsFileTransferPart(RcsControllerCall.call(
                 iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl
deleted file mode 100644
index 5774d00..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsMessageCreationParameters;
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.java b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
similarity index 80%
rename from telephony/java/android/telephony/ims/RcsMessageCreationParameters.java
rename to telephony/java/android/telephony/ims/RcsMessageCreationParams.java
index ff3f33e..9ac4dcd 100644
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParameters.java
+++ b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
@@ -21,18 +21,16 @@
 import android.annotation.CheckResult;
 import android.annotation.Nullable;
 import android.os.Parcel;
-import android.os.Parcelable;
-import android.telephony.SubscriptionInfo;
 
 /**
  * The collection of parameters to be passed into
- * {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParameters)} and
- * {@link RcsThread#addOutgoingMessage(RcsMessageCreationParameters)} to create and persist
+ * {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} and
+ * {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to create and persist
  * {@link RcsMessage}s on an {@link RcsThread}
  *
- * @hide TODO - make public
+ * @hide - TODO: make public
  */
-public class RcsMessageCreationParameters implements Parcelable {
+public class RcsMessageCreationParams {
     // The globally unique id of the RcsMessage to be created.
     private final String mRcsMessageGlobalId;
 
@@ -110,7 +108,7 @@
     /**
      * The base builder for creating {@link RcsMessage}s on {@link RcsThread}s.
      *
-     * @see RcsIncomingMessageCreationParameters
+     * @see RcsIncomingMessageCreationParams
      */
     public static class Builder {
         private String mRcsMessageGlobalId;
@@ -122,15 +120,7 @@
         private double mLongitude = LOCATION_NOT_SET;
 
         /**
-         * Creates a new {@link Builder} to create an instance of
-         * {@link RcsMessageCreationParameters}.
-         *
-         * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
-         *                             timestamp value in milliseconds passed after midnight,
-         *                             January 1, 1970 UTC
-         * @param subscriptionId The subscription ID that was used to send or receive this
-         *                       {@link RcsMessage}
-         * @see SubscriptionInfo#getSubscriptionId()
+         * @hide
          */
         public Builder(long originationTimestamp, int subscriptionId) {
             mOriginationTimestamp = originationTimestamp;
@@ -207,14 +197,14 @@
         }
 
         /**
-         * @hide
+         * @return Builds and returns a newly created {@link RcsMessageCreationParams}
          */
-        public RcsMessageCreationParameters build() {
-            return new RcsMessageCreationParameters(this);
+        public RcsMessageCreationParams build() {
+            return new RcsMessageCreationParams(this);
         }
     }
 
-    protected RcsMessageCreationParameters(Builder builder) {
+    protected RcsMessageCreationParams(Builder builder) {
         mRcsMessageGlobalId = builder.mRcsMessageGlobalId;
         mSubId = builder.mSubId;
         mMessageStatus = builder.mMessageStatus;
@@ -224,7 +214,10 @@
         mLongitude = builder.mLongitude;
     }
 
-    protected RcsMessageCreationParameters(Parcel in) {
+    /**
+     * @hide
+     */
+    RcsMessageCreationParams(Parcel in) {
         mRcsMessageGlobalId = in.readString();
         mSubId = in.readInt();
         mMessageStatus = in.readInt();
@@ -234,26 +227,10 @@
         mLongitude = in.readDouble();
     }
 
-    public static final Creator<RcsMessageCreationParameters> CREATOR =
-            new Creator<RcsMessageCreationParameters>() {
-                @Override
-                public RcsMessageCreationParameters createFromParcel(Parcel in) {
-                    return new RcsMessageCreationParameters(in);
-                }
-
-                @Override
-                public RcsMessageCreationParameters[] newArray(int size) {
-                    return new RcsMessageCreationParameters[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * @hide
+     */
+    public void writeToParcel(Parcel dest) {
         dest.writeString(mRcsMessageGlobalId);
         dest.writeInt(mSubId);
         dest.writeInt(mMessageStatus);
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl
deleted file mode 100644
index c325c23..0000000
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsMessageQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
similarity index 94%
rename from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
rename to telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
index 52e73ce..e9cbd9c 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsMessageQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.java b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
similarity index 86%
rename from telephony/java/android/telephony/ims/RcsMessageQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsMessageQueryParams.java
index c964cf9..fae0d97 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
@@ -29,12 +29,12 @@
 
 /**
  * The parameters to pass into
- * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} in order to select a
  * subset of {@link RcsMessage}s present in the message store.
  *
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
  */
-public class RcsMessageQueryParameters implements Parcelable {
+public final class RcsMessageQueryParams implements Parcelable {
     /**
      * @hide - not meant for public use
      */
@@ -60,28 +60,28 @@
 
     /**
      * Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return
+     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
      * {@link RcsIncomingMessage}s.
      */
     public static final int MESSAGE_TYPE_INCOMING = 0x0001;
 
     /**
      * Bitmask flag to be used with {@link Builder#setMessageType(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return
+     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return
      * {@link RcsOutgoingMessage}s.
      */
     public static final int MESSAGE_TYPE_OUTGOING = 0x0002;
 
     /**
      * Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return {@link RcsMessage}s
+     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
      * that have an {@link RcsFileTransferPart} attached.
      */
     public static final int MESSAGES_WITH_FILE_TRANSFERS = 0x0004;
 
     /**
      * Bitmask flag to be used with {@link Builder#setFileTransferPresence(int)} to make
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)} return {@link RcsMessage}s
+     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} return {@link RcsMessage}s
      * that don't have an {@link RcsFileTransferPart} attached.
      */
     public static final int MESSAGES_WITHOUT_FILE_TRANSFERS = 0x0008;
@@ -106,7 +106,7 @@
     // The thread that the results should be limited to
     private int mThreadId;
 
-    RcsMessageQueryParameters(int messageType, int fileTransferPresence, String messageLike,
+    RcsMessageQueryParams(int messageType, int fileTransferPresence, String messageLike,
             int threadId, @SortingProperty int sortingProperty, boolean isAscending, int limit) {
         mMessageType = messageType;
         mFileTransferPresence = fileTransferPresence;
@@ -118,7 +118,7 @@
     }
 
     /**
-     * @return Returns the type of {@link RcsMessage}s that this {@link RcsMessageQueryParameters}
+     * @return Returns the type of {@link RcsMessage}s that this {@link RcsMessageQueryParams}
      * is set to query for.
      */
     public int getMessageType() {
@@ -177,7 +177,7 @@
     }
 
     /**
-     * A helper class to build the {@link RcsMessageQueryParameters}.
+     * A helper class to build the {@link RcsMessageQueryParams}.
      */
     public static class Builder {
         private @SortingProperty int mSortingProperty;
@@ -189,8 +189,8 @@
         private int mThreadId = THREAD_ID_NOT_SET;
 
         /**
-         * Creates a new builder for {@link RcsMessageQueryParameters} to be used in
-         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+         * Creates a new builder for {@link RcsMessageQueryParams} to be used in
+         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
          *
          */
         public Builder() {
@@ -221,8 +221,8 @@
          *
          * @param messageType The type of message to be returned.
          * @return The same instance of the builder to chain parameters.
-         * @see RcsMessageQueryParameters#MESSAGE_TYPE_INCOMING
-         * @see RcsMessageQueryParameters#MESSAGE_TYPE_OUTGOING
+         * @see RcsMessageQueryParams#MESSAGE_TYPE_INCOMING
+         * @see RcsMessageQueryParams#MESSAGE_TYPE_OUTGOING
          */
         @CheckResult
         public Builder setMessageType(int messageType) {
@@ -235,8 +235,8 @@
          *
          * @param fileTransferPresence Whether file transfers should be included in the result
          * @return The same instance of the builder to chain parameters.
-         * @see RcsMessageQueryParameters#MESSAGES_WITH_FILE_TRANSFERS
-         * @see RcsMessageQueryParameters#MESSAGES_WITHOUT_FILE_TRANSFERS
+         * @see RcsMessageQueryParams#MESSAGES_WITH_FILE_TRANSFERS
+         * @see RcsMessageQueryParams#MESSAGES_WITHOUT_FILE_TRANSFERS
          */
         @CheckResult
         public Builder setFileTransferPresence(int fileTransferPresence) {
@@ -264,7 +264,7 @@
 
         /**
          * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsMessageQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+         * {@link RcsMessageQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
          *
          * @param sortingProperty against which property the results should be sorted
          * @return The same instance of the builder to chain parameters.
@@ -305,14 +305,14 @@
         }
 
         /**
-         * Builds the {@link RcsMessageQueryParameters} to use in
-         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+         * Builds the {@link RcsMessageQueryParams} to use in
+         * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
          *
-         * @return An instance of {@link RcsMessageQueryParameters} to use with the message
+         * @return An instance of {@link RcsMessageQueryParams} to use with the message
          * query.
          */
-        public RcsMessageQueryParameters build() {
-            return new RcsMessageQueryParameters(mMessageType, mFileTransferPresence, mMessageLike,
+        public RcsMessageQueryParams build() {
+            return new RcsMessageQueryParams(mMessageType, mFileTransferPresence, mMessageLike,
                     mThreadId, mSortingProperty, mIsAscending, mLimit);
         }
     }
@@ -320,7 +320,7 @@
     /**
      * Parcelable boilerplate below.
      */
-    protected RcsMessageQueryParameters(Parcel in) {
+    private RcsMessageQueryParams(Parcel in) {
         mMessageType = in.readInt();
         mFileTransferPresence = in.readInt();
         mMessageLike = in.readString();
@@ -330,16 +330,16 @@
         mThreadId = in.readInt();
     }
 
-    public static final Creator<RcsMessageQueryParameters> CREATOR =
-            new Creator<RcsMessageQueryParameters>() {
+    public static final Creator<RcsMessageQueryParams> CREATOR =
+            new Creator<RcsMessageQueryParams>() {
                 @Override
-                public RcsMessageQueryParameters createFromParcel(Parcel in) {
-                    return new RcsMessageQueryParameters(in);
+                public RcsMessageQueryParams createFromParcel(Parcel in) {
+                    return new RcsMessageQueryParams(in);
                 }
 
                 @Override
-                public RcsMessageQueryParameters[] newArray(int size) {
-                    return new RcsMessageQueryParameters[size];
+                public RcsMessageQueryParams[] newArray(int size) {
+                    return new RcsMessageQueryParams[size];
                 }
             };
 
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index c3846fd..5adab76 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -29,13 +29,13 @@
 import java.util.List;
 
 /**
- * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
  * call. This class allows getting the token for querying the next batch of messages in order to
  * prevent handling large amounts of data at once.
  *
- * @hide
+ * @hide - TODO: make public
  */
-public class RcsMessageQueryResult implements Parcelable {
+public final class RcsMessageQueryResult implements Parcelable {
     // The token to continue the query to get the next batch of results
     private RcsQueryContinuationToken mContinuationToken;
     // The message type and message ID pairs for all the messages in this query result
@@ -83,7 +83,7 @@
         return messages;
     }
 
-    protected RcsMessageQueryResult(Parcel in) {
+    private RcsMessageQueryResult(Parcel in) {
         mContinuationToken = in.readParcelable(
                 RcsQueryContinuationToken.class.getClassLoader());
         in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
diff --git a/telephony/java/android/telephony/ims/RcsMessageSnippet.java b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
index 9399c20..565bb99 100644
--- a/telephony/java/android/telephony/ims/RcsMessageSnippet.java
+++ b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
@@ -24,9 +24,9 @@
 /**
  * An immutable summary of the latest {@link RcsMessage} on an {@link RcsThread}
  *
- * @hide TODO: make public
+ * @hide - TODO: make public
  */
-public class RcsMessageSnippet implements Parcelable {
+public final class RcsMessageSnippet implements Parcelable {
     private final String mText;
     private final @RcsMessageStatus int mStatus;
     private final long mTimestamp;
@@ -65,7 +65,7 @@
         return mTimestamp;
     }
 
-    protected RcsMessageSnippet(Parcel in) {
+    private RcsMessageSnippet(Parcel in) {
         mText = in.readString();
         mStatus = in.readInt();
         mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index c8c36a8..eca5ed5 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -27,7 +27,7 @@
  * RcsMessageStore is the application interface to RcsProvider and provides access methods to
  * RCS related database tables.
  *
- * @hide - TODO make this public
+ * @hide - TODO: make public
  */
 public class RcsMessageStore {
     /**
@@ -39,7 +39,7 @@
      */
     @WorkerThread
     @NonNull
-    public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParameters queryParameters)
+    public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
             throws RcsMessageStoreException {
         return RcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters));
     }
@@ -68,7 +68,7 @@
     @WorkerThread
     @NonNull
     public RcsParticipantQueryResult getRcsParticipants(
-            @Nullable RcsParticipantQueryParameters queryParameters)
+            @Nullable RcsParticipantQueryParams queryParameters)
             throws RcsMessageStoreException {
         return RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters));
     }
@@ -99,7 +99,7 @@
     @WorkerThread
     @NonNull
     public RcsMessageQueryResult getRcsMessages(
-            @Nullable RcsMessageQueryParameters queryParameters) throws RcsMessageStoreException {
+            @Nullable RcsMessageQueryParams queryParameters) throws RcsMessageStoreException {
         return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
     }
 
@@ -127,7 +127,7 @@
     @WorkerThread
     @NonNull
     public RcsEventQueryResult getRcsEvents(
-            @Nullable RcsEventQueryParameters queryParameters) throws RcsMessageStoreException {
+            @Nullable RcsEventQueryParams queryParameters) throws RcsMessageStoreException {
         return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParameters));
     }
 
diff --git a/telephony/java/android/telephony/ims/RcsMessageStoreException.java b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
index e158f1a..7c00749 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStoreException.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
@@ -20,7 +20,7 @@
  * An exception that happened on {@link RcsMessageStore} or one of the derived storage classes in
  * {@link android.telephony.ims}
  *
- * @hide TODO: make public
+ * @hide - TODO: make public
  */
 public class RcsMessageStoreException extends Exception {
 
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 0bd55ec..dfcdee4 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -24,7 +24,7 @@
 /**
  * This is a single instance of a message sent over RCS.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class RcsOutgoingMessage extends RcsMessage {
     RcsOutgoingMessage(int id) {
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
similarity index 93%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
index 52e73ce..0c38d9f 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsOutgoingMessageCreationParams;
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
new file mode 100644
index 0000000..ca466e8
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
@@ -0,0 +1,89 @@
+/*
+ * 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.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@link RcsOutgoingMessageCreationParams} is a collection of parameters that should be passed
+ * into {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to generate an
+ * {@link RcsOutgoingMessage} on that {@link RcsThread}
+ *
+ * @hide - TODO: make public
+ */
+public final class RcsOutgoingMessageCreationParams extends RcsMessageCreationParams
+        implements Parcelable {
+    /**
+     * A builder to instantiate and persist an {@link RcsOutgoingMessage}
+     */
+    public static class Builder extends RcsMessageCreationParams.Builder {
+
+        /**
+         * Creates a new {@link Builder} to create an instance of
+         * {@link RcsOutgoingMessageCreationParams}.
+         *
+         * @param originationTimestamp The timestamp of {@link RcsMessage} creation. The origination
+         *                             timestamp value in milliseconds passed after midnight,
+         *                             January 1, 1970 UTC
+         * @param subscriptionId The subscription ID that was used to send or receive this
+         *                       {@link RcsMessage}
+         * @see android.telephony.SubscriptionInfo#getSubscriptionId()
+         */
+        public Builder(long originationTimestamp, int subscriptionId) {
+            super(originationTimestamp, subscriptionId);
+        }
+
+        /**
+         * Creates configuration parameters for a new message.
+         */
+        public RcsOutgoingMessageCreationParams build() {
+            return new RcsOutgoingMessageCreationParams(this);
+        }
+    }
+
+    private RcsOutgoingMessageCreationParams(Builder builder) {
+        super(builder);
+    }
+
+    private RcsOutgoingMessageCreationParams(Parcel in) {
+        super(in);
+    }
+
+    public static final Creator<RcsOutgoingMessageCreationParams> CREATOR =
+            new Creator<RcsOutgoingMessageCreationParams>() {
+                @Override
+                public RcsOutgoingMessageCreationParams createFromParcel(Parcel in) {
+                    return new RcsOutgoingMessageCreationParams(in);
+                }
+
+                @Override
+                public RcsOutgoingMessageCreationParams[] newArray(int size) {
+                    return new RcsOutgoingMessageCreationParams[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest);
+    }
+}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index b93f892..5a3062a 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -22,7 +22,7 @@
  * This class holds the delivery information of an {@link RcsOutgoingMessage} for each
  * {@link RcsParticipant} that the message was intended for.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class RcsOutgoingMessageDelivery {
     // The participant that this delivery is intended for
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index ce0ad2c..37b827b 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -21,7 +21,7 @@
 /**
  * RcsParticipant is an RCS capable contact that can participate in {@link RcsThread}s.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public class RcsParticipant {
     // The row ID of this participant in the database
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 04cdf86..aa278b3 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -18,18 +18,19 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * An event that indicates an {@link RcsParticipant}'s alias was changed. Please see US18-2 - GSMA
  * RCC.71 (RCS Universal Profile Service Definition Document)
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
-public class RcsParticipantAliasChangedEvent extends RcsEvent {
+public final class RcsParticipantAliasChangedEvent extends RcsEvent implements Parcelable {
     // The ID of the participant that changed their alias
-    private int mParticipantId;
+    private final int mParticipantId;
     // The new alias of the above participant
-    private String mNewAlias;
+    private final String mNewAlias;
 
     /**
      * Creates a new {@link RcsParticipantAliasChangedEvent}. This event is not persisted into
@@ -98,7 +99,7 @@
                 }
             };
 
-    protected RcsParticipantAliasChangedEvent(Parcel in) {
+    private RcsParticipantAliasChangedEvent(Parcel in) {
         super(in);
         mNewAlias = in.readString();
         mParticipantId = in.readInt();
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl
deleted file mode 100644
index ea8288c..0000000
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.ims;
-
-parcelable RcsParticipantQueryParameters;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
index 52e73ce..b7c0f93 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsParticipantQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
similarity index 89%
rename from telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
index 3611fc1..57c67fa 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
@@ -28,12 +28,12 @@
 
 /**
  * The parameters to pass into
- * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)} in order to select a
+ * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)} in order to select a
  * subset of {@link RcsThread}s present in the message store.
  *
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
  */
-public class RcsParticipantQueryParameters implements Parcelable {
+public final class RcsParticipantQueryParams implements Parcelable {
     /**
      * Flag to set with {@link Builder#setSortProperty(int)} to sort the results in the order of
      * creation time for faster query results
@@ -75,7 +75,7 @@
      */
     public static final String PARTICIPANT_QUERY_PARAMETERS_KEY = "participant_query_parameters";
 
-    RcsParticipantQueryParameters(int rcsThreadId, String aliasLike, String canonicalAddressLike,
+    RcsParticipantQueryParams(int rcsThreadId, String aliasLike, String canonicalAddressLike,
             @SortingProperty int sortingProperty, boolean isAscending,
             int limit) {
         mThreadId = rcsThreadId;
@@ -143,7 +143,7 @@
     }
 
     /**
-     * A helper class to build the {@link RcsParticipantQueryParameters}.
+     * A helper class to build the {@link RcsParticipantQueryParams}.
      */
     public static class Builder {
         private String mAliasLike;
@@ -154,8 +154,8 @@
         private int mThreadId;
 
         /**
-         * Creates a new builder for {@link RcsParticipantQueryParameters} to be used in
-         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+         * Creates a new builder for {@link RcsParticipantQueryParams} to be used in
+         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
          */
         public Builder() {
             // empty implementation
@@ -231,7 +231,7 @@
 
         /**
          * Sets the property where the results should be sorted against. Defaults to
-         * {@link RcsParticipantQueryParameters.SortingProperty#SORT_BY_CREATION_ORDER}
+         * {@link RcsParticipantQueryParams.SortingProperty#SORT_BY_CREATION_ORDER}
          *
          * @param sortingProperty against which property the results should be sorted
          * @return The same instance of the builder to chain parameters.
@@ -255,14 +255,14 @@
         }
 
         /**
-         * Builds the {@link RcsParticipantQueryParameters} to use in
-         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+         * Builds the {@link RcsParticipantQueryParams} to use in
+         * {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
          *
-         * @return An instance of {@link RcsParticipantQueryParameters} to use with the participant
+         * @return An instance of {@link RcsParticipantQueryParams} to use with the participant
          * query.
          */
-        public RcsParticipantQueryParameters build() {
-            return new RcsParticipantQueryParameters(mThreadId, mAliasLike, mCanonicalAddressLike,
+        public RcsParticipantQueryParams build() {
+            return new RcsParticipantQueryParams(mThreadId, mAliasLike, mCanonicalAddressLike,
                     mSortingProperty, mIsAscending, mLimit);
         }
     }
@@ -270,7 +270,7 @@
     /**
      * Parcelable boilerplate below.
      */
-    protected RcsParticipantQueryParameters(Parcel in) {
+    private RcsParticipantQueryParams(Parcel in) {
         mAliasLike = in.readString();
         mCanonicalAddressLike = in.readString();
         mSortingProperty = in.readInt();
@@ -279,16 +279,16 @@
         mThreadId = in.readInt();
     }
 
-    public static final Creator<RcsParticipantQueryParameters> CREATOR =
-            new Creator<RcsParticipantQueryParameters>() {
+    public static final Creator<RcsParticipantQueryParams> CREATOR =
+            new Creator<RcsParticipantQueryParams>() {
                 @Override
-                public RcsParticipantQueryParameters createFromParcel(Parcel in) {
-                    return new RcsParticipantQueryParameters(in);
+                public RcsParticipantQueryParams createFromParcel(Parcel in) {
+                    return new RcsParticipantQueryParams(in);
                 }
 
                 @Override
-                public RcsParticipantQueryParameters[] newArray(int size) {
-                    return new RcsParticipantQueryParameters[size];
+                public RcsParticipantQueryParams[] newArray(int size) {
+                    return new RcsParticipantQueryParams[size];
                 }
             };
 
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 2f4ab46..4eae39d 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -25,13 +25,13 @@
 import java.util.List;
 
 /**
- * The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
  * call. This class allows getting the token for querying the next batch of participants in order to
  * prevent handling large amounts of data at once.
  *
- * @hide
+ * @hide - TODO: make public
  */
-public class RcsParticipantQueryResult implements Parcelable {
+public final class RcsParticipantQueryResult implements Parcelable {
     // A token for the caller to continue their query for the next batch of results
     private RcsQueryContinuationToken mContinuationToken;
     // The list of participant IDs returned with this query
@@ -75,7 +75,7 @@
         return participantList;
     }
 
-    protected RcsParticipantQueryResult(Parcel in) {
+    private RcsParticipantQueryResult(Parcel in) {
         mContinuationToken = in.readParcelable(
                 RcsQueryContinuationToken.class.getClassLoader());
     }
diff --git a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
index e880651..c1ff396 100644
--- a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
+++ b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
@@ -24,11 +24,17 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * This interface allows using the same implementation for continuation token usage in
- * {@link com.android.providers.telephony.RcsProvider}
- * @hide - TODO make getQueryType() and types public - the rest should stay internal
+ * A token for enabling continuation queries. Instances are acquired through
+ * {@code getContinuationToken} on result objects after initial query is done.
+ *
+ * @see RcsEventQueryResult#getContinuationToken()
+ * @see RcsMessageQueryResult#getContinuationToken()
+ * @see RcsParticipantQueryResult#getContinuationToken()
+ * @see RcsThreadQueryResult#getContinuationToken()
+ *
+ * @hide - TODO: make public
  */
-public class RcsQueryContinuationToken implements Parcelable {
+public final class RcsQueryContinuationToken implements Parcelable {
     /**
      * Denotes that this {@link RcsQueryContinuationToken} token is meant to allow continuing
      * {@link RcsEvent} queries
@@ -116,7 +122,7 @@
         return mQueryType;
     }
 
-    protected RcsQueryContinuationToken(Parcel in) {
+    private RcsQueryContinuationToken(Parcel in) {
         mQueryType = in.readInt();
         mRawQuery = in.readString();
         mLimit = in.readInt();
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index 238f5e7..8865586 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -28,10 +28,13 @@
  * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
  * received and events that occurred on that thread.
  *
- * @hide - TODO(109759350) make this public
+ * @hide - TODO: make public
  */
 public abstract class RcsThread {
-    // The rcs_participant_thread_id that represents this thread in the database
+    /**
+     * The rcs_participant_thread_id that represents this thread in the database
+     * @hide
+     */
     protected int mThreadId;
 
     /**
@@ -59,10 +62,10 @@
     @WorkerThread
     @NonNull
     public RcsIncomingMessage addIncomingMessage(
-            @NonNull RcsIncomingMessageCreationParameters rcsIncomingMessageCreationParameters)
+            @NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
             throws RcsMessageStoreException {
         return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
-                mThreadId, rcsIncomingMessageCreationParameters)));
+                mThreadId, rcsIncomingMessageCreationParams)));
     }
 
     /**
@@ -73,10 +76,10 @@
     @WorkerThread
     @NonNull
     public RcsOutgoingMessage addOutgoingMessage(
-            @NonNull RcsMessageCreationParameters rcsMessageCreationParameters)
+            @NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
             throws RcsMessageStoreException {
         int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
-                mThreadId, rcsMessageCreationParameters));
+                mThreadId, rcsOutgoingMessageCreationParams));
 
         return new RcsOutgoingMessage(messageId);
     }
@@ -97,7 +100,7 @@
     /**
      * Convenience function for loading all the {@link RcsMessage}s in this {@link RcsThread}. For
      * a more detailed and paginated query, please use
-     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParameters)}
+     * {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
      *
      * @return Loads the {@link RcsMessage}s in this thread and returns them in an immutable list.
      * @throws RcsMessageStoreException if the messages could not be read from the storage
@@ -105,8 +108,8 @@
     @WorkerThread
     @NonNull
     public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
-        RcsMessageQueryParameters queryParameters =
-                new RcsMessageQueryParameters.Builder().setThread(this).build();
+        RcsMessageQueryParams queryParameters =
+                new RcsMessageQueryParams.Builder().setThread(this).build();
         return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
     }
 
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl b/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
similarity index 94%
copy from telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
copy to telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
index 52e73ce..3f351dc 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.aidl
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParams.aidl
@@ -17,4 +17,4 @@
 
 package android.telephony.ims;
 
-parcelable RcsThreadQueryParameters;
+parcelable RcsThreadQueryParams;
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
similarity index 86%
rename from telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
rename to telephony/java/android/telephony/ims/RcsThreadQueryParams.java
index 4aa4207..ba32e32 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParameters.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
@@ -33,22 +33,22 @@
 import java.util.Set;
 
 /**
- * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} in
+ * The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} in
  * order to select a subset of {@link RcsThread}s present in the message store.
  *
- * @hide TODO - make the Builder and builder() public. The rest should stay internal only.
+ * @hide - TODO: make public
  */
-public class RcsThreadQueryParameters implements Parcelable {
+public final class RcsThreadQueryParams implements Parcelable {
     /**
      * Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
-     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} return
+     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
      * {@link RcsGroupThread}s.
      */
     public static final int THREAD_TYPE_GROUP = 0x0001;
 
     /**
      * Bitmask flag to be used with {@link Builder#setThreadType(int)} to make
-     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)} return
+     * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} return
      * {@link Rcs1To1Thread}s.
      */
     public static final int THREAD_TYPE_1_TO_1 = 0x0002;
@@ -86,7 +86,7 @@
      */
     public static final String THREAD_QUERY_PARAMETERS_KEY = "thread_query_parameters";
 
-    RcsThreadQueryParameters(int threadType, Set<RcsParticipant> participants,
+    RcsThreadQueryParams(int threadType, Set<RcsParticipant> participants,
             int limit, int sortingProperty, boolean isAscending) {
         mThreadType = threadType;
         mRcsParticipantIds = convertParticipantSetToIdList(participants);
@@ -148,7 +148,7 @@
     }
 
     /**
-     * A helper class to build the {@link RcsThreadQueryParameters}.
+     * A helper class to build the {@link RcsThreadQueryParams}.
      */
     public static class Builder {
         private int mThreadType;
@@ -158,8 +158,8 @@
         private boolean mIsAscending;
 
         /**
-         * Constructs a {@link RcsThreadQueryParameters.Builder} to help build an
-         * {@link RcsThreadQueryParameters}
+         * Constructs a {@link RcsThreadQueryParams.Builder} to help build an
+         * {@link RcsThreadQueryParams}
          */
         public Builder() {
             mParticipants = new HashSet<>();
@@ -170,8 +170,8 @@
          *
          * @param threadType Whether to limit the query result to group threads.
          * @return The same instance of the builder to chain parameters.
-         * @see RcsThreadQueryParameters#THREAD_TYPE_GROUP
-         * @see RcsThreadQueryParameters#THREAD_TYPE_1_TO_1
+         * @see RcsThreadQueryParams#THREAD_TYPE_GROUP
+         * @see RcsThreadQueryParams#THREAD_TYPE_1_TO_1
          */
         @CheckResult
         public Builder setThreadType(int threadType) {
@@ -253,13 +253,13 @@
         }
 
         /**
-         * Builds the {@link RcsThreadQueryParameters} to use in
-         * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)}
+         * Builds the {@link RcsThreadQueryParams} to use in
+         * {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
          *
-         * @return An instance of {@link RcsThreadQueryParameters} to use with the thread query.
+         * @return An instance of {@link RcsThreadQueryParams} to use with the thread query.
          */
-        public RcsThreadQueryParameters build() {
-            return new RcsThreadQueryParameters(mThreadType, mParticipants, mLimit,
+        public RcsThreadQueryParams build() {
+            return new RcsThreadQueryParams(mThreadType, mParticipants, mLimit,
                     mSortingProperty, mIsAscending);
         }
     }
@@ -267,7 +267,7 @@
     /**
      * Parcelable boilerplate below.
      */
-    protected RcsThreadQueryParameters(Parcel in) {
+    private RcsThreadQueryParams(Parcel in) {
         mThreadType = in.readInt();
         mRcsParticipantIds = new ArrayList<>();
         in.readList(mRcsParticipantIds, Integer.class.getClassLoader());
@@ -276,16 +276,16 @@
         mIsAscending = in.readByte() == 1;
     }
 
-    public static final Creator<RcsThreadQueryParameters> CREATOR =
-            new Creator<RcsThreadQueryParameters>() {
+    public static final Creator<RcsThreadQueryParams> CREATOR =
+            new Creator<RcsThreadQueryParams>() {
                 @Override
-                public RcsThreadQueryParameters createFromParcel(Parcel in) {
-                    return new RcsThreadQueryParameters(in);
+                public RcsThreadQueryParams createFromParcel(Parcel in) {
+                    return new RcsThreadQueryParams(in);
                 }
 
                 @Override
-                public RcsThreadQueryParameters[] newArray(int size) {
-                    return new RcsThreadQueryParameters[size];
+                public RcsThreadQueryParams[] newArray(int size) {
+                    return new RcsThreadQueryParams[size];
                 }
             };
 
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index 6515933..a91126b 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -29,13 +29,13 @@
 import java.util.List;
 
 /**
- * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParameters)}
+ * The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
  * call. This class allows getting the token for querying the next batch of threads in order to
  * prevent handling large amounts of data at once.
  *
- * @hide
+ * @hide - TODO: make public
  */
-public class RcsThreadQueryResult implements Parcelable {
+public final class RcsThreadQueryResult implements Parcelable {
     // A token for the caller to continue their query for the next batch of results
     private RcsQueryContinuationToken mContinuationToken;
     // The list of thread IDs returned with this query
@@ -84,7 +84,7 @@
         return rcsThreads;
     }
 
-    protected RcsThreadQueryResult(Parcel in) {
+    private RcsThreadQueryResult(Parcel in) {
         mContinuationToken = in.readParcelable(
             RcsQueryContinuationToken.class.getClassLoader());
         mRcsThreadIds = new ArrayList<>();
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index a399786..2478f8c 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -17,18 +17,18 @@
 package android.telephony.ims.aidl;
 
 import android.net.Uri;
-import android.telephony.ims.RcsEventQueryParameters;
+import android.telephony.ims.RcsEventQueryParams;
 import android.telephony.ims.RcsEventQueryResult;
-import android.telephony.ims.RcsFileTransferCreationParameters;
-import android.telephony.ims.RcsIncomingMessageCreationParameters;
-import android.telephony.ims.RcsMessageCreationParameters;
+import android.telephony.ims.RcsFileTransferCreationParams;
+import android.telephony.ims.RcsIncomingMessageCreationParams;
 import android.telephony.ims.RcsMessageSnippet;
-import android.telephony.ims.RcsMessageQueryParameters;
+import android.telephony.ims.RcsMessageQueryParams;
 import android.telephony.ims.RcsMessageQueryResult;
-import android.telephony.ims.RcsParticipantQueryParameters;
+import android.telephony.ims.RcsOutgoingMessageCreationParams;
+import android.telephony.ims.RcsParticipantQueryParams;
 import android.telephony.ims.RcsParticipantQueryResult;
 import android.telephony.ims.RcsQueryContinuationToken;
-import android.telephony.ims.RcsThreadQueryParameters;
+import android.telephony.ims.RcsThreadQueryParams;
 import android.telephony.ims.RcsThreadQueryResult;
 
 /**
@@ -39,22 +39,22 @@
     /////////////////////////
     // RcsMessageStore APIs
     /////////////////////////
-    RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParameters queryParameters);
+    RcsThreadQueryResult getRcsThreads(in RcsThreadQueryParams queryParams);
 
     RcsThreadQueryResult getRcsThreadsWithToken(
         in RcsQueryContinuationToken continuationToken);
 
-    RcsParticipantQueryResult getParticipants(in RcsParticipantQueryParameters queryParameters);
+    RcsParticipantQueryResult getParticipants(in RcsParticipantQueryParams queryParams);
 
     RcsParticipantQueryResult getParticipantsWithToken(
         in RcsQueryContinuationToken continuationToken);
 
-    RcsMessageQueryResult getMessages(in RcsMessageQueryParameters queryParameters);
+    RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
 
     RcsMessageQueryResult getMessagesWithToken(
         in RcsQueryContinuationToken continuationToken);
 
-    RcsEventQueryResult getEvents(in RcsEventQueryParameters queryParameters);
+    RcsEventQueryResult getEvents(in RcsEventQueryParams queryParams);
 
     RcsEventQueryResult getEventsWithToken(
         in RcsQueryContinuationToken continuationToken);
@@ -74,11 +74,11 @@
 
     // Creates a new RcsIncomingMessage on the given thread and returns its row ID
     int addIncomingMessage(int rcsThreadId,
-            in RcsIncomingMessageCreationParameters rcsIncomingMessageCreationParameters);
+            in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams);
 
     // Creates a new RcsOutgoingMessage on the given thread and returns its row ID
     int addOutgoingMessage(int rcsThreadId,
-            in RcsMessageCreationParameters rcsMessageCreationParameters);
+            in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams);
 
     // TODO: modify RcsProvider URI's to allow deleting a message without specifying its thread
     void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup);
@@ -203,7 +203,7 @@
 
     // Performs the initial write to storage and returns the row ID.
     int storeFileTransfer(int messageId, boolean isIncoming,
-            in RcsFileTransferCreationParameters fileTransferCreationParameters);
+            in RcsFileTransferCreationParams fileTransferCreationParams);
 
     void deleteFileTransfer(int partId);
 
diff --git a/test-base/api/TEST_MAPPING b/test-base/api/TEST_MAPPING
new file mode 100644
index 0000000..3535954
--- /dev/null
+++ b/test-base/api/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAndroidTestBase27ApiSignatureTestCases"
+    }
+  ]
+}
diff --git a/test-mock/api/TEST_MAPPING b/test-mock/api/TEST_MAPPING
new file mode 100644
index 0000000..d1bd9af
--- /dev/null
+++ b/test-mock/api/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAndroidTestMockCurrentApiSignatureTestCases"
+    },
+    {
+      "name": "CtsCurrentApiSignatureTestCases"
+    }
+  ]
+}
diff --git a/test-runner/api/TEST_MAPPING b/test-runner/api/TEST_MAPPING
new file mode 100644
index 0000000..76ade3c
--- /dev/null
+++ b/test-runner/api/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsAndroidTestRunnerCurrentApiSignatureTestCases"
+    },
+    {
+      "name": "CtsCurrentApiSignatureTestCases"
+    }
+  ]
+}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java
deleted file mode 100644
index b4bcb5d..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParametersTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsParticipantQueryParameters;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsParticipantQueryParametersTest {
-
-    @Test
-    public void testCanUnparcel() {
-        RcsParticipantQueryParameters rcsParticipantQueryParameters =
-                new RcsParticipantQueryParameters.Builder()
-                        .setAliasLike("%alias_")
-                        .setCanonicalAddressLike("_canonical%")
-                        .setSortProperty(RcsParticipantQueryParameters.SORT_BY_CANONICAL_ADDRESS)
-                        .setSortDirection(true)
-                        .setResultLimit(432)
-                        .build();
-
-
-        Parcel parcel = Parcel.obtain();
-        rcsParticipantQueryParameters.writeToParcel(parcel,
-                rcsParticipantQueryParameters.describeContents());
-
-        parcel.setDataPosition(0);
-        rcsParticipantQueryParameters = RcsParticipantQueryParameters.CREATOR.createFromParcel(
-                parcel);
-
-        assertThat(rcsParticipantQueryParameters.getAliasLike()).isEqualTo("%alias_");
-        assertThat(rcsParticipantQueryParameters.getCanonicalAddressLike()).contains("_canonical%");
-        assertThat(rcsParticipantQueryParameters.getLimit()).isEqualTo(432);
-        assertThat(rcsParticipantQueryParameters.getSortingProperty()).isEqualTo(
-                RcsParticipantQueryParameters.SORT_BY_CANONICAL_ADDRESS);
-        assertThat(rcsParticipantQueryParameters.getSortDirection()).isTrue();
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
new file mode 100644
index 0000000..6361a39
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantQueryParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.ims;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.ims.RcsParticipantQueryParams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsParticipantQueryParamsTest {
+
+    @Test
+    public void testCanUnparcel() {
+        RcsParticipantQueryParams rcsParticipantQueryParams =
+                new RcsParticipantQueryParams.Builder()
+                        .setAliasLike("%alias_")
+                        .setCanonicalAddressLike("_canonical%")
+                        .setSortProperty(RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS)
+                        .setSortDirection(true)
+                        .setResultLimit(432)
+                        .build();
+
+
+        Parcel parcel = Parcel.obtain();
+        rcsParticipantQueryParams.writeToParcel(parcel,
+                rcsParticipantQueryParams.describeContents());
+
+        parcel.setDataPosition(0);
+        rcsParticipantQueryParams = RcsParticipantQueryParams.CREATOR.createFromParcel(
+                parcel);
+
+        assertThat(rcsParticipantQueryParams.getAliasLike()).isEqualTo("%alias_");
+        assertThat(rcsParticipantQueryParams.getCanonicalAddressLike()).contains("_canonical%");
+        assertThat(rcsParticipantQueryParams.getLimit()).isEqualTo(432);
+        assertThat(rcsParticipantQueryParams.getSortingProperty()).isEqualTo(
+                RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS);
+        assertThat(rcsParticipantQueryParams.getSortDirection()).isTrue();
+    }
+}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
deleted file mode 100644
index 0a70eec..0000000
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParametersTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.ims;
-
-import static android.telephony.ims.RcsThreadQueryParameters.SORT_BY_TIMESTAMP;
-import static android.telephony.ims.RcsThreadQueryParameters.THREAD_TYPE_GROUP;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.telephony.ims.RcsParticipant;
-import android.telephony.ims.RcsThreadQueryParameters;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class RcsThreadQueryParametersTest {
-
-    @Test
-    public void testCanUnparcel() {
-        RcsParticipant rcsParticipant = new RcsParticipant(1);
-        RcsThreadQueryParameters rcsThreadQueryParameters = new RcsThreadQueryParameters.Builder()
-                .setThreadType(THREAD_TYPE_GROUP)
-                .setParticipant(rcsParticipant)
-                .setResultLimit(50)
-                .setSortProperty(SORT_BY_TIMESTAMP)
-                .setSortDirection(true)
-                .build();
-
-        Parcel parcel = Parcel.obtain();
-        rcsThreadQueryParameters.writeToParcel(parcel, rcsThreadQueryParameters.describeContents());
-
-        parcel.setDataPosition(0);
-        rcsThreadQueryParameters = RcsThreadQueryParameters.CREATOR.createFromParcel(parcel);
-
-        assertThat(rcsThreadQueryParameters.getThreadType()).isEqualTo(THREAD_TYPE_GROUP);
-        assertThat(rcsThreadQueryParameters.getRcsParticipantsIds())
-                .contains(rcsParticipant.getId());
-        assertThat(rcsThreadQueryParameters.getLimit()).isEqualTo(50);
-        assertThat(rcsThreadQueryParameters.getSortingProperty()).isEqualTo(SORT_BY_TIMESTAMP);
-        assertThat(rcsThreadQueryParameters.getSortDirection()).isTrue();
-    }
-}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
new file mode 100644
index 0000000..beb4f8a
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.ims;
+
+import static android.telephony.ims.RcsThreadQueryParams.SORT_BY_TIMESTAMP;
+import static android.telephony.ims.RcsThreadQueryParams.THREAD_TYPE_GROUP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.ims.RcsParticipant;
+import android.telephony.ims.RcsThreadQueryParams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsThreadQueryParamsTest {
+
+    @Test
+    public void testCanUnparcel() {
+        RcsParticipant rcsParticipant = new RcsParticipant(1);
+        RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
+                .setThreadType(THREAD_TYPE_GROUP)
+                .setParticipant(rcsParticipant)
+                .setResultLimit(50)
+                .setSortProperty(SORT_BY_TIMESTAMP)
+                .setSortDirection(true)
+                .build();
+
+        Parcel parcel = Parcel.obtain();
+        rcsThreadQueryParams.writeToParcel(parcel, rcsThreadQueryParams.describeContents());
+
+        parcel.setDataPosition(0);
+        rcsThreadQueryParams = RcsThreadQueryParams.CREATOR.createFromParcel(parcel);
+
+        assertThat(rcsThreadQueryParams.getThreadType()).isEqualTo(THREAD_TYPE_GROUP);
+        assertThat(rcsThreadQueryParams.getRcsParticipantsIds())
+                .contains(rcsParticipant.getId());
+        assertThat(rcsThreadQueryParams.getLimit()).isEqualTo(50);
+        assertThat(rcsThreadQueryParams.getSortingProperty()).isEqualTo(SORT_BY_TIMESTAMP);
+        assertThat(rcsThreadQueryParams.getSortDirection()).isTrue();
+    }
+}
diff --git a/tests/utils/testutils/java/android/view/test/InsetsModeSession.java b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
new file mode 100644
index 0000000..c83dfa4
--- /dev/null
+++ b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.test;
+
+import android.view.ViewRootImpl;
+
+/**
+ * Session to set insets mode for {@link ViewRootImpl#sNewInsetsMode}.
+ */
+public class InsetsModeSession implements AutoCloseable {
+
+    private int mOldMode;
+
+    public InsetsModeSession(int flag) {
+        mOldMode = ViewRootImpl.sNewInsetsMode;
+        ViewRootImpl.sNewInsetsMode = flag;
+    }
+
+    @Override
+    public void close() throws Exception {
+        ViewRootImpl.sNewInsetsMode = mOldMode;
+    }
+}
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 55440d2..0270c72 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -688,7 +688,7 @@
     build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
 
     size_t i = 0;
-    // Print constants
+    // Print atom constants
     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
         atom != atoms.decls.end(); atom++) {
         string constant = make_constant_name(atom->name);
@@ -714,6 +714,30 @@
     fprintf(out, "};\n");
     fprintf(out, "\n");
 
+    // Print constants for the enum values.
+    fprintf(out, "//\n");
+    fprintf(out, "// Constants for enum values\n");
+    fprintf(out, "//\n\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+        atom != atoms.decls.end(); atom++) {
+        for (vector<AtomField>::const_iterator field = atom->fields.begin();
+            field != atom->fields.end(); field++) {
+            if (field->javaType == JAVA_TYPE_ENUM) {
+                fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+                    field->name.c_str());
+                for (map<int, string>::const_iterator value = field->enumValues.begin();
+                    value != field->enumValues.end(); value++) {
+                    fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+                        make_constant_name(atom->message).c_str(),
+                        make_constant_name(field->name).c_str(),
+                        make_constant_name(value->second).c_str(),
+                        value->first);
+                }
+                fprintf(out, "\n");
+            }
+        }
+    }
+
     fprintf(out, "struct BytesField {\n");
     fprintf(out,
             "  BytesField(char const* array, size_t len) : arg(array), "
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index c5b9cf1..3881e9e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -969,7 +969,8 @@
 
     /**
      * Returns MAC address set to be the local randomized MAC address.
-     * Does not guarantee that the returned address is valid for use.
+     * Depending on user preference, the device may or may not use the returned MAC address for
+     * connections to this network.
      * <p>
      * Information is restricted to Device Owner, Profile Owner, and Carrier apps
      * (which will only obtain addresses for configurations which they create). Other callers
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 289f99d..2cc1d83 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -981,7 +981,7 @@
      * @deprecated This API is non-functional and will have no impact.
      */
     @Deprecated
-    public static final int WIFI_MODE_FULL = 1;
+    public static final int WIFI_MODE_FULL = WifiProtoEnums.WIFI_MODE_FULL; // 1
 
     /**
      * In this Wi-Fi lock mode, Wi-Fi will be kept active,
@@ -995,7 +995,7 @@
      * @deprecated This API is non-functional and will have no impact.
      */
     @Deprecated
-    public static final int WIFI_MODE_SCAN_ONLY = 2;
+    public static final int WIFI_MODE_SCAN_ONLY = WifiProtoEnums.WIFI_MODE_SCAN_ONLY; // 2
 
     /**
      * In this Wi-Fi lock mode, Wi-Fi will not go to power save.
@@ -1013,7 +1013,7 @@
      * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_HIGH_PERF}
      * lock will have no impact.
      */
-    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
+    public static final int WIFI_MODE_FULL_HIGH_PERF = WifiProtoEnums.WIFI_MODE_FULL_HIGH_PERF; // 3
 
     /**
      * In this Wi-Fi lock mode, Wi-Fi will operate with a priority to achieve low latency.
@@ -1037,15 +1037,13 @@
      * Example use cases are real time gaming or virtual reality applications where
      * low latency is a key factor for user experience.
      * <p>
-     * When there is no support from the hardware, the {@link #WIFI_MODE_FULL_LOW_LATENCY}
-     * lock will cause the device not to go power save.
-     * <p>
      * Note: For an app which acquires both {@link #WIFI_MODE_FULL_LOW_LATENCY} and
      * {@link #WIFI_MODE_FULL_HIGH_PERF} locks, {@link #WIFI_MODE_FULL_LOW_LATENCY}
      * lock will be effective when app is running in foreground and screen is on,
      * while the {@link #WIFI_MODE_FULL_HIGH_PERF} lock will take effect otherwise.
      */
-    public static final int WIFI_MODE_FULL_LOW_LATENCY = 4;
+    public static final int WIFI_MODE_FULL_LOW_LATENCY =
+            WifiProtoEnums.WIFI_MODE_FULL_LOW_LATENCY; // 4
 
     /** Anything worse than or equal to this will show 0 bars. */
     @UnsupportedAppUsage
@@ -4876,4 +4874,4 @@
             throw e.rethrowFromSystemServer();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index a69c7a5..333b82c 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -421,7 +421,7 @@
          *      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
          *      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
          *                       MacAddress.fromString("ff:ff:ff:00:00:00"))
-         *      .buildNetworkSpecifier()
+         *      .build()
          * final NetworkRequest request =
          *      new NetworkRequest.Builder()
          *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 460c633..233fa2c 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -413,17 +413,17 @@
          * final WifiNetworkSuggestion suggestion1 =
          *      new Builder()
          *      .setSsid("test111111")
-         *      .buildNetworkSuggestion()
+         *      .build()
          * final WifiNetworkSuggestion suggestion2 =
          *      new Builder()
          *      .setSsid("test222222")
          *      .setWpa2Passphrase("test123456")
-         *      .buildNetworkSuggestion()
+         *      .build()
          * final WifiNetworkSuggestion suggestion3 =
          *      new Builder()
          *      .setSsid("test333333")
          *      .setWpa3Passphrase("test6789")
-         *      .buildNetworkSuggestion()
+         *      .build()
          * final List<WifiNetworkSuggestion> suggestionsList =
          *      new ArrayList<WifiNetworkSuggestion> {{
          *          add(suggestion1);