Merge "Update text alignment when using drawTextOnPath." into pi-dev
diff --git a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
index 7a32c0c..e2b75c3 100644
--- a/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
+++ b/apct-tests/perftests/core/src/android/database/SQLiteDatabasePerfTest.java
@@ -118,6 +118,52 @@
     }
 
     @Test
+    public void testCursorIterateForward() {
+        // A larger dataset is needed to exceed default CursorWindow size
+        int datasetSize = DEFAULT_DATASET_SIZE * 50;
+        insertT1TestDataSet(datasetSize);
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            try (Cursor cursor = mDatabase
+                    .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) {
+                int i = 0;
+                while(cursor.moveToNext()) {
+                    assertEquals(i, cursor.getInt(0));
+                    assertEquals(i, cursor.getInt(1));
+                    assertEquals("T1Value" + i, cursor.getString(2));
+                    assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d);
+                    i++;
+                }
+                assertEquals(datasetSize, i);
+            }
+        }
+    }
+
+    @Test
+    public void testCursorIterateBackwards() {
+        // A larger dataset is needed to exceed default CursorWindow size
+        int datasetSize = DEFAULT_DATASET_SIZE * 50;
+        insertT1TestDataSet(datasetSize);
+
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            try (Cursor cursor = mDatabase
+                    .rawQuery("SELECT _ID, COL_A, COL_B, COL_C FROM T1 ORDER BY _ID", null)) {
+                int i = datasetSize - 1;
+                while(cursor.moveToPosition(i)) {
+                    assertEquals(i, cursor.getInt(0));
+                    assertEquals(i, cursor.getInt(1));
+                    assertEquals("T1Value" + i, cursor.getString(2));
+                    assertEquals(1.1 * i, cursor.getDouble(3), 0.0000001d);
+                    i--;
+                }
+                assertEquals(-1, i);
+            }
+        }
+    }
+
+    @Test
     public void testInnerJoin() {
         mDatabase.setForeignKeyConstraintsEnabled(true);
         mDatabase.beginTransaction();
@@ -201,8 +247,12 @@
     }
 
     private void insertT1TestDataSet() {
+        insertT1TestDataSet(DEFAULT_DATASET_SIZE);
+    }
+
+    private void insertT1TestDataSet(int size) {
         mDatabase.beginTransaction();
-        for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) {
+        for (int i = 0; i < size; i++) {
             mDatabase.execSQL("INSERT INTO T1 VALUES (?, ?, ?, ?)",
                     new Object[]{i, i, "T1Value" + i, i * 1.1});
         }
diff --git a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
index dccb34b..fefda64 100644
--- a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
+++ b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
@@ -76,7 +76,7 @@
         }
 
         SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
-        for (int i = 0; i < ssb.length(); i += wordLen) {
+        for (int i = 0; i < ssb.length(); i += wordLen + 1) {
             final int spanStart = i;
             final int spanEnd = (i + wordLen) > ssb.length() ? ssb.length() : i + wordLen;
 
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index 55b97e7..dc34b7f 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -117,6 +117,26 @@
     }
 
     @Test
+    public void testNewLayout_RandomText_Selectable() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            final TextView textView = new TextView(getContext());
+            textView.setTextIsSelectable(true);
+            textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+            textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+            textView.setText(text);
+            Canvas.freeTextLayoutCaches();
+            state.resumeTiming();
+
+            textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+                TEXT_WIDTH, false);
+        }
+    }
+
+    @Test
     public void testNewLayout_PrecomputedText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -179,6 +199,24 @@
     }
 
     @Test
+    public void testSetText_RandomText_Selectable() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            final TextView textView = new TextView(getContext());
+            textView.setTextIsSelectable(true);
+            textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+            textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+            Canvas.freeTextLayoutCaches();
+            state.resumeTiming();
+
+            textView.setText(text);
+        }
+    }
+
+    @Test
     public void testSetText_PrecomputedText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -222,8 +260,8 @@
     @Test
     public void testOnMeasure_RandomText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
-        int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         while (state.keepRunning()) {
             state.pauseTiming();
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
@@ -240,10 +278,31 @@
     }
 
     @Test
+    public void testOnMeasure_RandomText_Selectable() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            final TestableTextView textView = new TestableTextView(getContext());
+            textView.setTextIsSelectable(true);
+            textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+            textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+            textView.setText(text);
+            textView.nullLayouts();
+            Canvas.freeTextLayoutCaches();
+            state.resumeTiming();
+
+            textView.onMeasure(width, height);
+        }
+    }
+
+    @Test
     public void testOnMeasure_PrecomputedText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
-        int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         while (state.keepRunning()) {
             state.pauseTiming();
             final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -265,8 +324,8 @@
     @Test
     public void testOnMeasure_PrecomputedText_Selectable() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
-        int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         while (state.keepRunning()) {
             state.pauseTiming();
             final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -289,8 +348,8 @@
     @Test
     public void testOnDraw_RandomText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
-        int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
@@ -299,8 +358,34 @@
             textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
             textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
             textView.setText(text);
+            textView.measure(width, height);
+            textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
+            final DisplayListCanvas c = node.start(
+                textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
-            textView.onMeasure(width, height);
+            Canvas.freeTextLayoutCaches();
+            state.resumeTiming();
+
+            textView.onDraw(c);
+        }
+    }
+
+    @Test
+    public void testOnDraw_RandomText_Selectable() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final RenderNode node = RenderNode.create("benchmark", null);
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            final TestableTextView textView = new TestableTextView(getContext());
+            textView.setTextIsSelectable(true);
+            textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+            textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+            textView.setText(text);
+            textView.measure(width, height);
+            textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
             final DisplayListCanvas c = node.start(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
@@ -314,8 +399,8 @@
     @Test
     public void testOnDraw_PrecomputedText() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
-        int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+        int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+        int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final RenderNode node = RenderNode.create("benchmark", null);
         while (state.keepRunning()) {
             state.pauseTiming();
@@ -327,8 +412,8 @@
             final TestableTextView textView = new TestableTextView(getContext());
             textView.setTextMetricsParams(params);
             textView.setText(text);
-            textView.nullLayouts();
-            textView.onMeasure(width, height);
+            textView.measure(width, height);
+            textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
             final DisplayListCanvas c = node.start(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
@@ -356,8 +441,8 @@
             textView.setTextIsSelectable(true);
             textView.setTextMetricsParams(params);
             textView.setText(text);
-            textView.nullLayouts();
-            textView.onMeasure(width, height);
+            textView.measure(width, height);
+            textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
             final DisplayListCanvas c = node.start(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
diff --git a/api/current.txt b/api/current.txt
index 26fe641..eab90be 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7266,6 +7266,7 @@
   public class SliceManager {
     method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
     method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>);
+    method public java.util.List<android.net.Uri> getPinnedSlices();
     method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
     method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri);
     method public android.net.Uri mapIntentToUri(android.content.Intent);
@@ -7418,12 +7419,14 @@
     method public int getEventType();
     method public java.lang.String getPackageName();
     method public java.lang.String getShortcutId();
+    method public int getStandbyBucket();
     method public long getTimeStamp();
     field public static final int CONFIGURATION_CHANGE = 5; // 0x5
     field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
     field public static final int MOVE_TO_FOREGROUND = 1; // 0x1
     field public static final int NONE = 0; // 0x0
     field public static final int SHORTCUT_INVOCATION = 8; // 0x8
+    field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
     field public static final int USER_INTERACTION = 7; // 0x7
   }
 
@@ -14436,6 +14439,7 @@
     method public static android.graphics.Typeface createFromFile(java.lang.String);
     method public static android.graphics.Typeface defaultFromStyle(int);
     method public int getStyle();
+    method public int getWeight();
     method public final boolean isBold();
     method public final boolean isItalic();
     field public static final int BOLD = 1; // 0x1
@@ -16434,8 +16438,8 @@
   }
 
   public final class SessionConfiguration {
-    ctor public SessionConfiguration(int, java.util.List<android.hardware.camera2.params.OutputConfiguration>, java.util.concurrent.Executor, android.hardware.camera2.CameraCaptureSession.StateCallback);
-    method public java.util.concurrent.Executor getExecutor();
+    ctor public SessionConfiguration(int, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler);
+    method public android.os.Handler getHandler();
     method public android.hardware.camera2.params.InputConfiguration getInputConfiguration();
     method public java.util.List<android.hardware.camera2.params.OutputConfiguration> getOutputConfigurations();
     method public android.hardware.camera2.CaptureRequest getSessionParameters();
@@ -28676,7 +28680,7 @@
     field public static final int IEEE8021X = 3; // 0x3
     field public static final int NONE = 0; // 0x0
     field public static final int WPA_EAP = 2; // 0x2
-    field public static final deprecated int WPA_PSK = 1; // 0x1
+    field public static final int WPA_PSK = 1; // 0x1
     field public static final java.lang.String[] strings;
     field public static final java.lang.String varName = "key_mgmt";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 43425cb..288fb00 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -261,6 +261,7 @@
 
   public class AppOpsManager {
     method public static java.lang.String[] getOpStrs();
+    method public void setMode(java.lang.String, int, java.lang.String, int);
     method public void setUidMode(java.lang.String, int, int);
     field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
     field public static final java.lang.String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
@@ -718,10 +719,8 @@
 
   public static final class UsageEvents.Event {
     method public java.lang.String getNotificationChannelId();
-    method public int getStandbyBucket();
     field public static final int NOTIFICATION_INTERRUPTION = 12; // 0xc
     field public static final int NOTIFICATION_SEEN = 10; // 0xa
-    field public static final int STANDBY_BUCKET_CHANGED = 11; // 0xb
   }
 
   public final class UsageStatsManager {
@@ -5261,12 +5260,13 @@
   }
 
   public class UiccSlotInfo implements android.os.Parcelable {
-    ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
+    ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean);
     method public int describeContents();
     method public java.lang.String getCardId();
     method public int getCardStateInfo();
     method public boolean getIsActive();
     method public boolean getIsEuicc();
+    method public boolean getIsExtendedApduSupported();
     method public int getLogicalSlotIdx();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -6127,19 +6127,24 @@
   }
 
   public final class ImsFeatureConfiguration implements android.os.Parcelable {
-    ctor public ImsFeatureConfiguration();
     method public int describeContents();
-    method public int[] getServiceFeatures();
+    method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
   }
 
   public static class ImsFeatureConfiguration.Builder {
     ctor public ImsFeatureConfiguration.Builder();
-    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
     method public android.telephony.ims.stub.ImsFeatureConfiguration build();
   }
 
+  public static final class ImsFeatureConfiguration.FeatureSlotPair {
+    ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+    field public final int featureType;
+    field public final int slotId;
+  }
+
   public class ImsMultiEndpointImplBase {
     ctor public ImsMultiEndpointImplBase();
     method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
diff --git a/api/test-current.txt b/api/test-current.txt
index 9d67f4c..54ddd5d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1,3 +1,12 @@
+package android {
+
+  public static final class Manifest.permission {
+    field public static final java.lang.String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
+    field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+  }
+
+}
+
 package android.animation {
 
   public class ValueAnimator extends android.animation.Animator {
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 7f0a26c..50a5ddd 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -82,10 +82,8 @@
 statsd_common_shared_libraries := \
     libbase \
     libbinder \
-    libcutils \
     libincident \
     liblog \
-    libselinux \
     libutils \
     libservices \
     libprotoutil \
@@ -198,7 +196,7 @@
     tests/e2e/WakelockDuration_e2e_test.cpp \
     tests/e2e/MetricConditionLink_e2e_test.cpp \
     tests/e2e/Attribution_e2e_test.cpp \
-    tests/e2e/GaugeMetric_e2e_test.cpp \
+    tests/e2e/GaugeMetric_e2e_push_test.cpp \
     tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \
     tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \
     tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -308,4 +306,4 @@
 statsd_common_shared_libraries:=
 
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/cmds/statsd/benchmark/filter_value_benchmark.cpp b/cmds/statsd/benchmark/filter_value_benchmark.cpp
index 66c4def..cfe477d 100644
--- a/cmds/statsd/benchmark/filter_value_benchmark.cpp
+++ b/cmds/statsd/benchmark/filter_value_benchmark.cpp
@@ -54,28 +54,12 @@
     translateFieldMatcher(field_matcher, &matchers);
 
     while (state.KeepRunning()) {
-        vector<HashableDimensionKey> output;
-        filterValues(matchers, event.getValues(), &output);
-    }
-}
-
-BENCHMARK(BM_FilterValue);
-
-static void BM_FilterValue2(benchmark::State& state) {
-    LogEvent event(1, 100000);
-    FieldMatcher field_matcher;
-    createLogEventAndMatcher(&event, &field_matcher);
-
-    std::vector<Matcher> matchers;
-    translateFieldMatcher(field_matcher, &matchers);
-
-    while (state.KeepRunning()) {
         HashableDimensionKey output;
         filterValues(matchers, event.getValues(), &output);
     }
 }
 
-BENCHMARK(BM_FilterValue2);
+BENCHMARK(BM_FilterValue);
 
 }  //  namespace statsd
 }  //  namespace os
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 0c9b701..dfd8705 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -48,6 +48,11 @@
         return true;
     }
 
+    if (matcher.hasAllPositionMatcher() &&
+        (mField & (matcher.mMask & kClearAllPositionMatcherMask)) == matcher.mMatcher.getField()) {
+        return true;
+    }
+
     return false;
 }
 
@@ -67,6 +72,10 @@
             return;
         }
         switch (matcher.position()) {
+            case Position::ALL:
+                pos[depth] = 0x00;
+                mask[depth] = 0x7f;
+                break;
             case Position::ANY:
                 pos[depth] = 0;
                 mask[depth] = 0;
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 0e3ae06..f7ce23b 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -30,6 +30,7 @@
 const int32_t kMaxLogDepth = 2;
 const int32_t kLastBitMask = 0x80;
 const int32_t kClearLastBitDeco = 0x7f;
+const int32_t kClearAllPositionMatcherMask = 0xffff00ff;
 
 enum Type { UNKNOWN, INT, LONG, FLOAT, STRING };
 
@@ -205,6 +206,7 @@
  * First: [Matcher Field] 0x02010101  [Mask]0xff7f7f7f
  * Last:  [Matcher Field] 0x02018001  [Mask]0xff7f807f
  * Any:   [Matcher Field] 0x02010001  [Mask]0xff7f007f
+ * All:   [Matcher Field] 0x02010001  [Mask]0xff7f7f7f
  *
  * [To match a log Field with a Matcher] we apply the bit mask to the log Field and check if
  * the result is equal to the Matcher Field. That's a bit wise AND operation + check if 2 ints are
@@ -226,9 +228,21 @@
         return mMask;
     }
 
+    inline int32_t getRawMaskAtDepth(int32_t depth) const {
+        int32_t field = (mMask & 0x00ffffff);
+        int32_t shift = 8 * (kMaxLogDepth - depth);
+        int32_t mask = 0xff << shift;
+
+        return (field & mask) >> shift;
+    }
+
+    bool hasAllPositionMatcher() const {
+        return mMatcher.getDepth() == 2 && getRawMaskAtDepth(1) == 0x7f;
+    }
+
     bool hasAnyPositionMatcher(int* prefix) const {
-        if (mMatcher.getDepth() == 2 && mMatcher.getRawPosAtDepth(2) == 0) {
-            (*prefix) = mMatcher.getPrefix(2);
+        if (mMatcher.getDepth() == 2 && mMatcher.getRawPosAtDepth(1) == 0) {
+            (*prefix) = mMatcher.getPrefix(1);
             return true;
         }
         return false;
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index d0c8311..7103034 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -61,125 +61,22 @@
 
 bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values,
                   HashableDimensionKey* output) {
-    for (size_t i = 0; i < matcherFields.size(); ++i) {
-        const auto& matcher = matcherFields[i];
-        bool found = false;
-        for (const auto& value : values) {
+    size_t num_matches = 0;
+    for (const auto& value : values) {
+        for (size_t i = 0; i < matcherFields.size(); ++i) {
+            const auto& matcher = matcherFields[i];
             // TODO: potential optimization here to break early because all fields are naturally
             // sorted.
             if (value.mField.matches(matcher)) {
                 output->addValue(value);
-                output->mutableValue(i)->mField.setTag(value.mField.getTag());
-                output->mutableValue(i)->mField.setField(value.mField.getField() & matcher.mMask);
-                found = true;
-                break;
-            }
-        }
-
-        if (!found) {
-            VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(),
-                   matcher.mMatcher.getField());
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// Filter fields using the matchers and output the results as a HashableDimensionKey.
-// Note: HashableDimensionKey is just a wrapper for vector<FieldValue>
-bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue>& values,
-                  vector<HashableDimensionKey>* output) {
-    output->push_back(HashableDimensionKey());
-    // Top level is only tag id. Now take the real child matchers
-    int prevAnyMatcherPrefix = 0;
-    size_t prevPrevFanout = 0;
-    size_t prevFanout = 0;
-
-    // For each matcher get matched results.
-    vector<FieldValue> matchedResults(2);
-    for (const auto& matcher : matcherFields) {
-        size_t num_matches = 0;
-        for (const auto& value : values) {
-            // TODO: potential optimization here to break early because all fields are naturally
-            // sorted.
-            if (value.mField.matches(matcher)) {
-                if (num_matches >= matchedResults.size()) {
-                    matchedResults.resize(num_matches * 2);
-                }
-                matchedResults[num_matches].mField.setTag(value.mField.getTag());
-                matchedResults[num_matches].mField.setField(value.mField.getField() & matcher.mMask);
-                matchedResults[num_matches].mValue = value.mValue;
+                output->mutableValue(num_matches)->mField.setTag(value.mField.getTag());
+                output->mutableValue(num_matches)->mField.setField(
+                    value.mField.getField() & matcher.mMask);
                 num_matches++;
             }
         }
-
-        if (num_matches == 0) {
-            VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(),
-                   matcher.mMatcher.getField());
-            continue;
-        }
-
-        if (num_matches == 1) {
-            for (auto& dimension : *output) {
-                dimension.addValue(matchedResults[0]);
-            }
-            prevAnyMatcherPrefix = 0;
-            prevFanout = 0;
-            continue;
-        }
-
-        // All the complexity below is because we support ANY in dimension.
-        bool createFanout = true;
-        // createFanout is true when the matcher doesn't need to follow the prev matcher's
-        // order.
-        // e.g., get (uid, tag) from any position in attribution. because we have translated
-        // it as 2 matchers, they need to follow the same ordering, we can't create a cross
-        // product of all uid and tags.
-        // However, if the 2 matchers have different prefix, they will create a cross product
-        // e.g., [any uid] [any some other repeated field], we will create a cross product for them
-        if (prevAnyMatcherPrefix != 0) {
-            int anyMatcherPrefix = 0;
-            bool isAnyMatcher = matcher.hasAnyPositionMatcher(&anyMatcherPrefix);
-            if (isAnyMatcher && anyMatcherPrefix == prevAnyMatcherPrefix) {
-                createFanout = false;
-            } else {
-                prevAnyMatcherPrefix = anyMatcherPrefix;
-            }
-        }
-
-        // Each matcher should match exact one field, unless position is ANY
-        // When x number of fields matches a matcher, the returned dimension
-        // size is multiplied by x.
-        int oldSize;
-        if (createFanout) {
-            // First create fanout (fanout size is matchedResults.Size which could be one,
-            // which means we do nothing here)
-            oldSize = output->size();
-            for (size_t i = 1; i < num_matches; i++) {
-                output->insert(output->end(), output->begin(), output->begin() + oldSize);
-            }
-            prevPrevFanout = oldSize;
-            prevFanout = num_matches;
-        } else {
-            // If we should not create fanout, e.g., uid tag from same position should be remain
-            // together.
-            oldSize = prevPrevFanout;
-            if (prevFanout != num_matches) {
-                // sanity check.
-                ALOGE("2 Any matcher result in different output");
-                return false;
-            }
-        }
-        // now add the matched field value to output
-        for (size_t i = 0; i < num_matches; i++) {
-            for (int j = 0; j < oldSize; j++) {
-                (*output)[i * oldSize + j].addValue(matchedResults[i]);
-            }
-        }
     }
-
-    return output->size() > 0 && (*output)[0].getValues().size() > 0;
+    return num_matches > 0;
 }
 
 void filterGaugeValues(const std::vector<Matcher>& matcherFields,
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index 4cfed88..6f4941f 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -122,17 +122,14 @@
 /**
  * Creating HashableDimensionKeys from FieldValues using matcher.
  *
- * This function may make modifications to the Field if the matcher has Position=LAST or ANY in
- * it. This is because: for example, when we create dimension from last uid in attribution chain,
+ * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL
+ * in it. This is because: for example, when we create dimension from last uid in attribution chain,
  * In one event, uid 1000 is at position 5 and it's the last
  * In another event, uid 1000 is at position 6, and it's the last
  * these 2 events should be mapped to the same dimension.  So we will remove the original position
  * from the dimension key for the uid field (by applying 0x80 bit mask).
  */
 bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
-                  std::vector<HashableDimensionKey>* output);
-// This function is used when there is at most one output dimension key. (no ANY matcher)
-bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values,
                   HashableDimensionKey* output);
 
 /**
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 02d4dc9..8f72a8f 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -62,6 +62,9 @@
 const int FIELD_ID_UID_MAP = 2;
 const int FIELD_ID_LAST_REPORT_ELAPSED_NANOS = 3;
 const int FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS = 4;
+const int FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS = 5;
+const int FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS = 6;
+
 
 #define STATS_DATA_DIR "/data/misc/stats-data"
 
@@ -260,6 +263,8 @@
             proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
 
     int64_t lastReportTimeNs = it->second->getLastReportTimeNs();
+    int64_t lastReportWallClockNs = it->second->getLastReportWallClockNs();
+
     // First, fill in ConfigMetricsReport using current data on memory, which
     // starts from filling in StatsLogReport's.
     it->second->onDumpReport(dumpTimeStampNs, &proto);
@@ -276,6 +281,10 @@
                 (long long)lastReportTimeNs);
     proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_ELAPSED_NANOS,
                 (long long)dumpTimeStampNs);
+    proto.write(FIELD_TYPE_INT64 | FIELD_ID_LAST_REPORT_WALL_CLOCK_NANOS,
+                (long long)lastReportWallClockNs);
+    proto.write(FIELD_TYPE_INT64 | FIELD_ID_CURRENT_REPORT_WALL_CLOCK_NANOS,
+                (long long)getWallClockNs());
 
     // End of ConfigMetricsReport (reports).
     proto.end(reportsToken);
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 8db8200..8b42146 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -121,7 +121,8 @@
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3);
     FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1);
     FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2);
-    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
+    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
+    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
@@ -138,6 +139,7 @@
     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_NoLink_AND_CombinationCondition);
     FRIEND_TEST(DimensionInConditionE2eTest, TestDurationMetric_Link_AND_CombinationCondition);
 
+
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8ba35b7..298f494 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -110,6 +110,11 @@
         BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
         BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
         BluetoothA2dpAudioStateChanged bluetooth_a2dp_audio_state_changed = 69;
+        UsbConnectorStateChanged usb_connector_changed = 70;
+        SpeakerImpedanceReported speaker_impedance_reported = 71;
+        HardwareFailed hardware_failed = 72;
+        PhysicalDropDetected physical_drop_detected = 73;
+        ChargeCyclesReported charge_cycles_reported = 74;
         // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
     }
 
@@ -965,6 +970,108 @@
 }
 
 /**
+ * Logs when something is plugged into or removed from the USB-C connector.
+ *
+ * Logged from:
+ *  Vendor USB HAL.
+ */
+message UsbConnectorStateChanged {
+    enum State {
+      DISCONNECTED = 0;
+      CONNECTED = 1;
+    }
+    optional State state = 1;
+}
+
+/**
+ * Logs the reported speaker impedance.
+ *
+ * Logged from:
+ *  Vendor audio implementation.
+ */
+message SpeakerImpedanceReported {
+    optional int32 speaker_location = 1;
+    optional int32 impedance = 2;
+}
+
+/**
+ * Logs the report of a failed hardware.
+ *
+ * Logged from:
+ *  Vendor HALs.
+ *
+ */
+message HardwareFailed {
+    enum HardwareType {
+        HARDWARE_FAILED_UNKNOWN = 0;
+        HARDWARE_FAILED_MICROPHONE = 1;
+        HARDWARE_FAILED_CODEC = 2;
+        HARDWARE_FAILED_SPEAKER = 3;
+        HARDWARE_FAILED_FINGERPRINT = 4;
+    }
+    optional HardwareType hardware_type = 1;
+
+    /* hardware_location allows vendors to differentiate between multiple instances of
+    * the same hardware_type.  The specific locations are vendor defined integers,
+    * referring to board-specific numbering schemes.
+    */
+    optional int32 hardware_location = 2;
+
+    /* failure_code is specific to the HardwareType of the failed hardware.
+     * It should use the enum values defined below.
+     */
+    enum MicrophoneFailureCode {
+        MICROPHONE_FAILURE_COMPLETE = 0;
+    }
+    enum CodecFailureCode {
+        CODEC_FAILURE_COMPLETE = 0;
+    }
+    enum SpeakerFailureCode {
+        SPEAKER_FAILURE_COMPLETE = 0;
+        SPEAKER_FAILURE_HIGH_Z = 1;
+        SPEAKER_FAILURE_SHORT = 2;
+    }
+    enum FingerprintFailureCode {
+        FINGERPRINT_FAILURE_COMPLETE = 0;
+        FINGERPRINT_SENSOR_BROKEN = 1;
+        FINGERPRINT_TOO_MANY_DEAD_PIXELS = 2;
+    }
+    optional int32 failure_code = 3;
+}
+
+/**
+ * Log an event when the device has been physically dropped.
+ * Reported from the /vendor partition.
+ */
+message PhysicalDropDetected {
+    // Confidence that the event was actually a drop, 0 -> 100
+    optional int32 confidence_pctg = 1;
+    // Peak acceleration of the drop, in 1/1000s of a g.
+    optional int32 accel_peak_thousandths_g = 2;
+}
+
+/**
+ * Log bucketed battery charge cycles.
+ *
+ * Each bucket represents cycles of the battery past
+ * a given charge point.  For example, bucket 1 is the
+ * lowest 1/8th of the battery, and bucket 8 is 100%.
+ *
+ * Logged from:
+ * /sys/class/power_supply/bms/cycle_count, via Vendor.
+ */
+message ChargeCyclesReported {
+    optional int32 cycle_bucket_1 = 1;
+    optional int32 cycle_bucket_2 = 2;
+    optional int32 cycle_bucket_3 = 3;
+    optional int32 cycle_bucket_4 = 4;
+    optional int32 cycle_bucket_5 = 5;
+    optional int32 cycle_bucket_6 = 6;
+    optional int32 cycle_bucket_7 = 7;
+    optional int32 cycle_bucket_8 = 8;
+}
+
+/**
  * Logs the duration of a davey (jank of >=700ms) when it occurs
  *
  * Logged from:
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 4913aef..73efb39 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -327,25 +327,7 @@
         // have both sliced and unsliced version of a predicate.
         handleConditionEvent(outputValue, matchedState == 1, &overallState, &overallChanged);
     } else {
-        std::vector<HashableDimensionKey> outputValues;
-        filterValues(mOutputDimensions, event.getValues(), &outputValues);
-
-        // If this event has multiple nodes in the attribution chain,  this log event probably will
-        // generate multiple dimensions. If so, we will find if the condition changes for any
-        // dimension and ask the corresponding metric producer to verify whether the actual sliced
-        // condition has changed or not.
-        // A high level assumption is that a predicate is either sliced or unsliced. We will never
-        // have both sliced and unsliced version of a predicate.
-        for (const HashableDimensionKey& outputValue : outputValues) {
-            ConditionState tempState;
-            bool tempChanged = false;
-            handleConditionEvent(outputValue, matchedState == 1, &tempState, &tempChanged);
-            if (tempChanged) {
-                overallChanged = true;
-            }
-            // ConditionState's | operator is overridden
-            overallState = overallState | tempState;
-        }
+        ALOGE("The condition tracker should not be sliced by ANY position matcher.");
     }
     conditionCache[mIndex] = overallState;
     conditionChangedCache[mIndex] = overallChanged;
diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateTracker.cpp
index c68875c..fe1740b 100644
--- a/cmds/statsd/src/condition/StateTracker.cpp
+++ b/cmds/statsd/src/condition/StateTracker.cpp
@@ -137,21 +137,18 @@
 
     VLOG("StateTracker evaluate event %s", event.ToString().c_str());
 
-    vector<HashableDimensionKey> keys;
-    vector<HashableDimensionKey> outputs;
-    filterValues(mPrimaryKeys, event.getValues(), &keys);
-    filterValues(mOutputDimensions, event.getValues(), &outputs);
-    if (keys.size() != 1 || outputs.size() != 1) {
-        ALOGE("More than 1 states in the event?? panic now!");
+    // Primary key can exclusive fields must be simple fields. so there won't be more than
+    // one keys matched.
+    HashableDimensionKey primaryKey;
+    HashableDimensionKey state;
+    if (!filterValues(mPrimaryKeys, event.getValues(), &primaryKey) ||
+        !filterValues(mOutputDimensions, event.getValues(), &state)) {
+        ALOGE("Failed to filter fields in the event?? panic now!");
         conditionCache[mIndex] =
                 mSlicedState.size() > 0 ? ConditionState::kTrue : ConditionState::kFalse;
         conditionChangedCache[mIndex] = false;
         return;
     }
-    // Primary key can exclusive fields must be simple fields. so there won't be more than
-    // one keys matched.
-    const auto& primaryKey = keys[0];
-    const auto& state = outputs[0];
     hitGuardRail(primaryKey);
 
     VLOG("StateTracker: key %s state %s", primaryKey.toString().c_str(), state.toString().c_str());
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index d0f55ab..f5310a4 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -68,12 +68,25 @@
     {
         lock_guard <mutex> lock(mMutex);
 
+        auto it = mConfigs.find(key);
+
+        const int numBytes = config.ByteSize();
+        vector<uint8_t> buffer(numBytes);
+        config.SerializeToArray(&buffer[0], numBytes);
+
+        const bool isDuplicate =
+            it != mConfigs.end() &&
+            StorageManager::hasIdenticalConfig(key, buffer);
+
+        // Update saved file on disk. We still update timestamp of file when
+        // there exists a duplicate configuration to avoid garbage collection.
+        update_saved_configs_locked(key, buffer, numBytes);
+
+        if (isDuplicate) return;
+
         // Add to set
         mConfigs.insert(key);
 
-        // Save to disk
-        update_saved_configs_locked(key, config);
-
         for (sp<ConfigListener> listener : mListeners) {
             broadcastList.push_back(listener);
         }
@@ -137,7 +150,6 @@
     {
         lock_guard <mutex> lock(mMutex);
 
-
         for (auto it = mConfigs.begin(); it != mConfigs.end();) {
             // Remove from map
             if (it->GetUid() == uid) {
@@ -230,16 +242,16 @@
     }
 }
 
-void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) {
+void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
+                                                const vector<uint8_t>& buffer,
+                                                const int numBytes) {
     // If there is a pre-existing config with same key we should first delete it.
     remove_saved_configs(key);
 
     // Then we save the latest config.
-    string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
-                                    key.GetUid(), (long long)key.GetId());
-    const int numBytes = config.ByteSize();
-    vector<uint8_t> buffer(numBytes);
-    config.SerializeToArray(&buffer[0], numBytes);
+    string file_name =
+        StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
+                     key.GetUid(), (long long)key.GetId());
     StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
 }
 
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index a0c1c1c..9a38188a 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -115,7 +115,9 @@
     /**
      * Save the configs to disk.
      */
-    void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config);
+    void update_saved_configs_locked(const ConfigKey& key,
+                                     const std::vector<uint8_t>& buffer,
+                                     const int numBytes);
 
     /**
      * Remove saved configs from disk.
@@ -123,7 +125,7 @@
     void remove_saved_configs(const ConfigKey& key);
 
     /**
-     * The Configs that have been set. Each config should
+     * Config keys that have been set.
      */
     std::set<ConfigKey> mConfigs;
 
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index c6c4d13..7a55f60 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -21,6 +21,7 @@
 #include <android/util/ProtoOutputStream.h>
 #include "../stats_log_util.h"
 #include "statslog.h"
+#include "storage/StorageManager.h"
 
 namespace android {
 namespace os {
@@ -403,6 +404,8 @@
             fprintf(out, "alert %lld declared %d times\n", (long long)stats.first, stats.second);
         }
     }
+    fprintf(out, "********Disk Usage stats***********\n");
+    StorageManager::printStats(out);
     fprintf(out, "********Pushed Atom stats***********\n");
     const size_t atomCounts = mPushedAtomStats.size();
     for (size_t i = 2; i < atomCounts; i++) {
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 364d4e9..b7105b3 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -185,6 +185,9 @@
                 ranges.push_back(std::make_pair(newStart, end));
                 break;
             }
+            case Position::ALL:
+                ALOGE("Not supported: field matcher with ALL position.");
+                break;
             case Position::POSITION_UNKNOWN:
                 break;
         }
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 22b2a30..8e8a529 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -99,6 +99,24 @@
     VLOG("~CountMetricProducer() called");
 }
 
+void CountMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+    if (mCurrentSlicedCounter == nullptr ||
+        mCurrentSlicedCounter->size() == 0) {
+        return;
+    }
+
+    fprintf(out, "CountMetric %lld dimension size %lu\n", (long long)mMetricId,
+            (unsigned long)mCurrentSlicedCounter->size());
+    if (verbose) {
+        for (const auto& it : *mCurrentSlicedCounter) {
+            fprintf(out, "\t(what)%s\t(condition)%s  %lld\n",
+                it.first.getDimensionKeyInWhat().toString().c_str(),
+                it.first.getDimensionKeyInCondition().toString().c_str(),
+                (unsigned long long)it.second);
+        }
+    }
+}
+
 void CountMetricProducer::onSlicedConditionMayChangeLocked(const uint64_t eventTime) {
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
 }
@@ -249,7 +267,6 @@
     } else {
         info.mBucketEndNs = fullBucketEndTimeNs;
     }
-    info.mBucketNum = mCurrentBucketNum;
     for (const auto& counter : *mCurrentSlicedCounter) {
         info.mCount = counter.second;
         auto& bucketList = mPastBuckets[counter.first];
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 1d8e42b..ef738ac 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -36,7 +36,6 @@
     int64_t mBucketStartNs;
     int64_t mBucketEndNs;
     int64_t mCount;
-    uint64_t mBucketNum;
 };
 
 class CountMetricProducer : public MetricProducer {
@@ -67,7 +66,7 @@
     // Internal function to calculate the current used bytes.
     size_t byteSizeLocked() const override;
 
-    void dumpStatesLocked(FILE* out, bool verbose) const override{};
+    void dumpStatesLocked(FILE* out, bool verbose) const override;
 
     void dropDataLocked(const uint64_t dropTimeNs) override;
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index bc09683..c6b9405 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -88,6 +88,12 @@
         translateFieldMatcher(internalDimensions, &mInternalDimensions);
         mContainANYPositionInInternalDimensions = HasPositionANY(internalDimensions);
     }
+    if (mContainANYPositionInInternalDimensions) {
+        ALOGE("Position ANY in internal dimension not supported.");
+    }
+    if (mContainANYPositionInDimensionsInWhat) {
+        ALOGE("Position ANY in dimension_in_what not supported.");
+    }
 
     if (metric.has_dimensions_in_condition()) {
         translateFieldMatcher(metric.dimensions_in_condition(), &mDimensionsInCondition);
@@ -589,18 +595,10 @@
         it->second->noteStart(DEFAULT_DIMENSION_KEY, condition,
                               event.GetElapsedTimestampNs(), conditionKeys);
     } else {
-        if (mContainANYPositionInInternalDimensions) {
-            std::vector<HashableDimensionKey> dimensionKeys;
-            filterValues(mInternalDimensions, event.getValues(), &dimensionKeys);
-            for (const auto& key : dimensionKeys) {
-                it->second->noteStart(key, condition, event.GetElapsedTimestampNs(), conditionKeys);
-            }
-        } else {
-            HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
-            filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
-            it->second->noteStart(
-                dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
-        }
+        HashableDimensionKey dimensionKey = DEFAULT_DIMENSION_KEY;
+        filterValues(mInternalDimensions, event.getValues(), &dimensionKey);
+        it->second->noteStart(
+            dimensionKey, condition, event.GetElapsedTimestampNs(), conditionKeys);
     }
 
 }
@@ -612,8 +610,8 @@
     ALOGW("Not used in duration tracker.");
 }
 
-void DurationMetricProducer::onMatchedLogEventLocked_simple(const size_t matcherIndex,
-                                                            const LogEvent& event) {
+void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
+                                                     const LogEvent& event) {
     uint64_t eventTimeNs = event.GetElapsedTimestampNs();
     if (eventTimeNs < mStartTimeNs) {
         return;
@@ -712,117 +710,6 @@
     }
 }
 
-void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
-                                                     const LogEvent& event) {
-    if (!mContainANYPositionInDimensionsInWhat) {
-        onMatchedLogEventLocked_simple(matcherIndex, event);
-        return;
-    }
-
-    uint64_t eventTimeNs = event.GetElapsedTimestampNs();
-    if (eventTimeNs < mStartTimeNs) {
-        return;
-    }
-
-    flushIfNeededLocked(event.GetElapsedTimestampNs());
-
-    // Handles Stopall events.
-    if (matcherIndex == mStopAllIndex) {
-        for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
-            for (auto& pair : whatIt.second) {
-                pair.second->noteStopAll(event.GetElapsedTimestampNs());
-            }
-        }
-        return;
-    }
-
-    vector<HashableDimensionKey> dimensionInWhatValues;
-    if (!mDimensionsInWhat.empty()) {
-        filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues);
-    } else {
-        dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY);
-    }
-
-    // Handles Stop events.
-    if (matcherIndex == mStopIndex) {
-        if (mUseWhatDimensionAsInternalDimension) {
-            for (const HashableDimensionKey& whatKey : dimensionInWhatValues) {
-                auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatKey);
-                if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
-                    for (const auto& condIt : whatIt->second) {
-                        condIt.second->noteStop(whatKey, event.GetElapsedTimestampNs(), false);
-                    }
-                }
-            }
-            return;
-        }
-
-        HashableDimensionKey internalDimensionKey = DEFAULT_DIMENSION_KEY;
-        if (!mInternalDimensions.empty()) {
-            filterValues(mInternalDimensions, event.getValues(), &internalDimensionKey);
-        }
-
-        for (const HashableDimensionKey& whatDimension : dimensionInWhatValues) {
-            auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension);
-            if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
-                for (const auto& condIt : whatIt->second) {
-                    condIt.second->noteStop(
-                        internalDimensionKey, event.GetElapsedTimestampNs(), false);
-                }
-            }
-        }
-        return;
-    }
-
-    bool condition;
-    ConditionKey conditionKey;
-    std::unordered_set<HashableDimensionKey> dimensionKeysInCondition;
-    if (mConditionSliced) {
-        for (const auto& link : mMetric2ConditionLinks) {
-            getDimensionForCondition(event.getValues(), link, &conditionKey[link.conditionId]);
-        }
-
-        auto conditionState =
-            mWizard->query(mConditionTrackerIndex, conditionKey, mDimensionsInCondition,
-                           !mSameConditionDimensionsInTracker,
-                           !mHasLinksToAllConditionDimensionsInTracker,
-                           &dimensionKeysInCondition);
-        condition = (conditionState == ConditionState::kTrue);
-        if (mDimensionsInCondition.empty() && condition) {
-            dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
-        }
-    } else {
-        condition = mCondition;
-        if (condition) {
-            dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
-        }
-    }
-
-    for (const auto& whatDimension : dimensionInWhatValues) {
-        if (dimensionKeysInCondition.empty()) {
-            handleStartEvent(MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
-                             conditionKey, condition, event);
-        } else {
-            auto whatIt = mCurrentSlicedDurationTrackerMap.find(whatDimension);
-            // If the what dimension is already there, we should update all the trackers even
-            // the condition is false.
-            if (whatIt != mCurrentSlicedDurationTrackerMap.end()) {
-                for (const auto& condIt : whatIt->second) {
-                    const bool cond = dimensionKeysInCondition.find(condIt.first) !=
-                            dimensionKeysInCondition.end();
-                    handleStartEvent(MetricDimensionKey(whatDimension, condIt.first),
-                                     conditionKey, cond, event);
-                    dimensionKeysInCondition.erase(condIt.first);
-                }
-            }
-            for (const auto& conditionDimension : dimensionKeysInCondition) {
-                handleStartEvent(MetricDimensionKey(whatDimension, conditionDimension),
-                                 conditionKey, condition, event);
-            }
-        }
-    }
-}
-
 size_t DurationMetricProducer::byteSizeLocked() const {
     size_t totalSize = 0;
     for (const auto& pair : mPastBuckets) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 6746e11..985749d 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -52,8 +52,6 @@
 protected:
     void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) override;
 
-    void onMatchedLogEventLocked_simple(const size_t matcherIndex, const LogEvent& event);
-
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
             const ConditionKey& conditionKeys, bool condition,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index e479e5c..55a281e 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -56,6 +56,7 @@
 const int FIELD_ID_END_BUCKET_ELAPSED_NANOS = 2;
 const int FIELD_ID_ATOM = 3;
 const int FIELD_ID_ELAPSED_ATOM_TIMESTAMP = 4;
+const int FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP = 5;
 
 GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
                                          const int conditionIndex,
@@ -126,6 +127,24 @@
     }
 }
 
+void GaugeMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+    if (mCurrentSlicedBucket == nullptr ||
+        mCurrentSlicedBucket->size() == 0) {
+        return;
+    }
+
+    fprintf(out, "GaugeMetric %lld dimension size %lu\n", (long long)mMetricId,
+            (unsigned long)mCurrentSlicedBucket->size());
+    if (verbose) {
+        for (const auto& it : *mCurrentSlicedBucket) {
+            fprintf(out, "\t(what)%s\t(condition)%s  %d atoms\n",
+                it.first.getDimensionKeyInWhat().toString().c_str(),
+                it.first.getDimensionKeyInCondition().toString().c_str(),
+                (int)it.second.size());
+        }
+    }
+}
+
 void GaugeMetricProducer::onDumpReportLocked(const uint64_t dumpTimeNs,
                                              ProtoOutputStream* protoOutput) {
     VLOG("gauge metric %lld report now...", (long long)mMetricId);
@@ -168,21 +187,28 @@
                                (long long)bucket.mBucketEndNs);
 
             if (!bucket.mGaugeAtoms.empty()) {
-                uint64_t atomsToken =
-                    protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
                 for (const auto& atom : bucket.mGaugeAtoms) {
+                    uint64_t atomsToken =
+                        protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                           FIELD_ID_ATOM);
                     writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput);
+                    protoOutput->end(atomsToken);
                 }
-                protoOutput->end(atomsToken);
+                const bool truncateTimestamp =
+                    android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) ==
+                    android::util::kNotTruncatingTimestampAtomWhiteList.end();
+                const int64_t wall_clock_ns = truncateTimestamp ?
+                    truncateTimestampNsToFiveMinutes(getWallClockNs()) : getWallClockNs();
                 for (const auto& atom : bucket.mGaugeAtoms) {
-                    const bool truncateTimestamp =
-                        android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) ==
-                        android::util::kNotTruncatingTimestampAtomWhiteList.end();
                     int64_t timestampNs =  truncateTimestamp ?
                         truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps;
                     protoOutput->write(
                         FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
                         (long long)timestampNs);
+                    protoOutput->write(
+                        FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED |
+                            FIELD_ID_WALL_CLOCK_ATOM_TIMESTAMP,
+                        (long long)wall_clock_ns);
                 }
             }
             protoOutput->end(bucketInfoToken);
@@ -393,7 +419,6 @@
     } else {
         info.mBucketEndNs = fullBucketEndTimeNs;
     }
-    info.mBucketNum = mCurrentBucketNum;
 
     for (const auto& slice : *mCurrentSlicedBucket) {
         info.mGaugeAtoms = slice.second;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index ca8dc75..dd6aff4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -44,7 +44,6 @@
     int64_t mBucketStartNs;
     int64_t mBucketEndNs;
     std::vector<GaugeAtom> mGaugeAtoms;
-    uint64_t mBucketNum;
 };
 
 typedef std::unordered_map<MetricDimensionKey, std::vector<GaugeAtom>>
@@ -106,7 +105,7 @@
     // Internal function to calculate the current used bytes.
     size_t byteSizeLocked() const override;
 
-    void dumpStatesLocked(FILE* out, bool verbose) const override{};
+    void dumpStatesLocked(FILE* out, bool verbose) const override;
 
     void dropDataLocked(const uint64_t dropTimeNs) override;
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 6c90b03..f4495a1 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -53,39 +53,17 @@
         dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
     }
 
-    if (mContainANYPositionInDimensionsInWhat) {
-        vector<HashableDimensionKey> dimensionInWhatValues;
-        if (!mDimensionsInWhat.empty()) {
-            filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhatValues);
-        } else {
-            dimensionInWhatValues.push_back(DEFAULT_DIMENSION_KEY);
-        }
-
-        for (const auto& whatDimension : dimensionInWhatValues) {
-            for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
-                onMatchedLogEventInternalLocked(
-                        matcherIndex, MetricDimensionKey(whatDimension, conditionDimensionKey),
-                        conditionKey, condition, event);
-            }
-            if (dimensionKeysInCondition.empty()) {
-                onMatchedLogEventInternalLocked(
-                        matcherIndex, MetricDimensionKey(whatDimension, DEFAULT_DIMENSION_KEY),
-                         conditionKey, condition, event);
-            }
-        }
-    } else {
-        HashableDimensionKey dimensionInWhat;
-        filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
-        MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY);
-        for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
-            metricKey.setDimensionKeyInCondition(conditionDimensionKey);
-            onMatchedLogEventInternalLocked(
-                    matcherIndex, metricKey, conditionKey, condition, event);
-        }
-        if (dimensionKeysInCondition.empty()) {
-            onMatchedLogEventInternalLocked(
-                    matcherIndex, metricKey, conditionKey, condition, event);
-        }
+    HashableDimensionKey dimensionInWhat;
+    filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
+    MetricDimensionKey metricKey(dimensionInWhat, DEFAULT_DIMENSION_KEY);
+    for (const auto& conditionDimensionKey : dimensionKeysInCondition) {
+        metricKey.setDimensionKeyInCondition(conditionDimensionKey);
+        onMatchedLogEventInternalLocked(
+                matcherIndex, metricKey, conditionKey, condition, event);
+    }
+    if (dimensionKeysInCondition.empty()) {
+        onMatchedLogEventInternalLocked(
+                matcherIndex, metricKey, conditionKey, condition, event);
     }
 
  }
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 1ca59a3..6209bbe 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -53,7 +53,9 @@
                                const sp<UidMap> &uidMap,
                                const sp<AlarmMonitor>& anomalyAlarmMonitor,
                                const sp<AlarmMonitor>& periodicAlarmMonitor)
-    : mConfigKey(key), mUidMap(uidMap), mLastReportTimeNs(timeBaseSec * NS_PER_SEC) {
+    : mConfigKey(key), mUidMap(uidMap),
+      mLastReportTimeNs(timeBaseSec * NS_PER_SEC),
+      mLastReportWallClockNs(getWallClockNs()) {
     mConfigValid =
             initStatsdConfig(key, config, *uidMap, anomalyAlarmMonitor, periodicAlarmMonitor,
                              timeBaseSec, mTagIds, mAllAtomMatchers,
@@ -193,6 +195,7 @@
         }
     }
     mLastReportTimeNs = dumpTimeStampNs;
+    mLastReportWallClockNs = getWallClockNs();
     VLOG("=========================Metric Reports End==========================");
 }
 
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index dbab814..46a9b34 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -69,10 +69,14 @@
     void dumpStates(FILE* out, bool verbose);
 
     // Returns the elapsed realtime when this metric manager last reported metrics.
-    uint64_t getLastReportTimeNs() {
+    inline int64_t getLastReportTimeNs() const {
         return mLastReportTimeNs;
     };
 
+    inline int64_t getLastReportWallClockNs() const {
+        return mLastReportWallClockNs;
+    };
+
     virtual void dropData(const uint64_t dropTimeNs);
 
     // Config source owner can call onDumpReport() to get all the metrics collected.
@@ -89,7 +93,8 @@
 
     bool mConfigValid = false;
 
-    uint64_t mLastReportTimeNs;
+    int64_t mLastReportTimeNs;
+    int64_t mLastReportWallClockNs;
 
     // The uid log sources from StatsdConfig.
     std::vector<int32_t> mAllowedUid;
@@ -158,7 +163,8 @@
 
     FRIEND_TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensions);
     FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
-    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSlice);
+    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
+    FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_Link_OR_CombinationCondition);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 09913dc..767260d 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -243,6 +243,23 @@
     }
 }
 
+void ValueMetricProducer::dumpStatesLocked(FILE* out, bool verbose) const {
+    if (mCurrentSlicedBucket.size() == 0) {
+        return;
+    }
+
+    fprintf(out, "ValueMetric %lld dimension size %lu\n", (long long)mMetricId,
+            (unsigned long)mCurrentSlicedBucket.size());
+    if (verbose) {
+        for (const auto& it : mCurrentSlicedBucket) {
+            fprintf(out, "\t(what)%s\t(condition)%s  (value)%lld\n",
+                it.first.getDimensionKeyInWhat().toString().c_str(),
+                it.first.getDimensionKeyInCondition().toString().c_str(),
+                (unsigned long long)it.second.sum);
+        }
+    }
+}
+
 bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
     // ===========GuardRail==============
     // 1. Report the tuple count if the tuple count > soft limit
@@ -355,7 +372,6 @@
     } else {
         info.mBucketEndNs = fullBucketEndTimeNs;
     }
-    info.mBucketNum = mCurrentBucketNum;
 
     int tainted = 0;
     for (const auto& slice : mCurrentSlicedBucket) {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 5e42bd2..be57183 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -34,7 +34,6 @@
     int64_t mBucketStartNs;
     int64_t mBucketEndNs;
     int64_t mValue;
-    uint64_t mBucketNum;
 };
 
 class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
@@ -99,7 +98,7 @@
     // Internal function to calculate the current used bytes.
     size_t byteSizeLocked() const override;
 
-    void dumpStatesLocked(FILE* out, bool verbose) const override{};
+    void dumpStatesLocked(FILE* out, bool verbose) const override;
 
     // Util function to flush the old packet.
     void flushIfNeededLocked(const uint64_t& eventTime) override;
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 7b3393f..bfb1ec7 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -55,7 +55,6 @@
     uint64_t mBucketStartNs;
     uint64_t mBucketEndNs;
     uint64_t mDuration;
-    uint64_t mBucketNum;
 };
 
 class DurationTracker {
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index 8e0bf26..058940d 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -219,7 +219,6 @@
         DurationBucket info;
         info.mBucketStartNs = mCurrentBucketStartTimeNs;
         info.mBucketEndNs = currentBucketEndTimeNs;
-        info.mBucketNum = mCurrentBucketNum;
         info.mDuration = mDuration;
         (*output)[mEventKey].push_back(info);
         VLOG("  final duration for last bucket: %lld", (long long)mDuration);
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 2358415..c8a5016 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -165,13 +165,12 @@
         DurationBucket current_info;
         current_info.mBucketStartNs = mCurrentBucketStartTimeNs;
         current_info.mBucketEndNs = currentBucketEndTimeNs;
-        current_info.mBucketNum = mCurrentBucketNum;
         current_info.mDuration = mDuration;
         (*output)[mEventKey].push_back(current_info);
         mDurationFullBucket += mDuration;
         if (eventTimeNs > fullBucketEnd) {
             // End of full bucket, can send to anomaly tracker now.
-            addPastBucketToAnomalyTrackers(mDurationFullBucket, current_info.mBucketNum);
+            addPastBucketToAnomalyTrackers(mDurationFullBucket, mCurrentBucketNum);
             mDurationFullBucket = 0;
         }
         VLOG("  duration: %lld", (long long)current_info.mDuration);
@@ -182,12 +181,11 @@
             DurationBucket info;
             info.mBucketStartNs = fullBucketEnd + mBucketSizeNs * (i - 1);
             info.mBucketEndNs = info.mBucketStartNs + mBucketSizeNs;
-            info.mBucketNum = mCurrentBucketNum + i;
             info.mDuration = mBucketSizeNs;
             (*output)[mEventKey].push_back(info);
             // Safe to send these buckets to anomaly tracker since they must be full buckets.
             // If it's a partial bucket, numBucketsForward would be 0.
-            addPastBucketToAnomalyTrackers(info.mDuration, info.mBucketNum);
+            addPastBucketToAnomalyTrackers(info.mDuration, mCurrentBucketNum + i);
             VLOG("  add filling bucket with duration %lld", (long long)info.mDuration);
         }
     }
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 3c5f5a2..0412538 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -46,7 +46,7 @@
 
   optional Atom atom = 2;
 
-  optional int64 wall_clock_timestamp_sec = 3;
+  optional int64 wall_clock_timestamp_nanos = 3;
 }
 
 message CountBucketInfo {
@@ -105,6 +105,8 @@
   repeated Atom atom = 3;
 
   repeated int64 elapsed_timestamp_nanos = 4;
+
+  repeated int64 wall_clock_timestamp_nanos = 5;
 }
 
 message GaugeMetricData {
@@ -154,6 +156,10 @@
   optional int64 last_report_elapsed_nanos = 3;
 
   optional int64 current_report_elapsed_nanos = 4;
+
+  optional int64 last_report_wall_clock_nanos = 5;
+
+  optional int64 current_report_wall_clock_nanos = 6;
 }
 
 message ConfigMetricsReportList {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 1c99e2a..2c70191 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -31,6 +31,8 @@
   LAST = 2;
 
   ANY = 3;
+
+  ALL = 4;
 }
 
 enum TimeUnit {
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 781eced..cd41f53 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -245,6 +245,45 @@
     }
 }
 
+bool StorageManager::hasIdenticalConfig(const ConfigKey& key,
+                                        const vector<uint8_t>& config) {
+    unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR),
+                                             closedir);
+    if (dir == NULL) {
+        VLOG("Directory does not exist: %s", STATS_SERVICE_DIR);
+        return false;
+    }
+
+    const char* suffix =
+            StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()).c_str();
+
+    dirent* de;
+    while ((de = readdir(dir.get()))) {
+        char* name = de->d_name;
+        if (name[0] == '.') {
+            continue;
+        }
+        size_t nameLen = strlen(name);
+        size_t suffixLen = strlen(suffix);
+        // There can be at most one file that matches this suffix (config key).
+        if (suffixLen <= nameLen &&
+                strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) {
+            int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(),
+                                  O_RDONLY | O_CLOEXEC);
+            if (fd != -1) {
+                string content;
+                if (android::base::ReadFdToString(fd, &content)) {
+                    vector<uint8_t> vec(content.begin(), content.end());
+                    if (vec == config) {
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
 void StorageManager::trimToFit(const char* path) {
     unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
     if (dir == NULL) {
@@ -306,6 +345,53 @@
     }
 }
 
+void StorageManager::printStats(FILE* out) {
+    printDirStats(out, STATS_SERVICE_DIR);
+    printDirStats(out, STATS_DATA_DIR);
+}
+
+void StorageManager::printDirStats(FILE* out, const char* path) {
+    fprintf(out, "Printing stats of %s\n", path);
+    unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
+    if (dir == NULL) {
+        VLOG("Path %s does not exist", path);
+        return;
+    }
+    dirent* de;
+    int fileCount = 0;
+    int totalFileSize = 0;
+    while ((de = readdir(dir.get()))) {
+        char* name = de->d_name;
+        if (name[0] == '.') {
+            continue;
+        }
+        int64_t result[3];
+        parseFileName(name, result);
+        if (result[0] == -1) continue;
+        int64_t timestamp = result[0];
+        int64_t uid = result[1];
+        int64_t configID = result[2];
+        fprintf(out, "\t #%d, Last updated: %lld, UID: %d, Config ID: %lld",
+                fileCount + 1,
+                (long long)timestamp,
+                (int)uid,
+                (long long)configID);
+        string file_name = getFilePath(path, timestamp, uid, configID);
+        ifstream file(file_name.c_str(), ifstream::in | ifstream::binary);
+        if (file.is_open()) {
+            file.seekg(0, ios::end);
+            int fileSize = file.tellg();
+            file.close();
+            fprintf(out, ", File Size: %d bytes", fileSize);
+            totalFileSize += fileSize;
+        }
+        fprintf(out, "\n");
+        fileCount++;
+    }
+    fprintf(out, "\tTotal number of files: %d, Total size of files: %d bytes.\n",
+            fileCount, totalFileSize);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index 6c8ed0a..4b75628 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -78,6 +78,23 @@
      * files, accumulation of outdated files.
      */
     static void trimToFit(const char* dir);
+
+    /**
+     * Returns true if there already exists identical configuration on device.
+     */
+    static bool hasIdenticalConfig(const ConfigKey& key,
+                                   const vector<uint8_t>& config);
+
+    /**
+     * Prints disk usage statistics related to statsd.
+     */
+    static void printStats(FILE* out);
+
+private:
+    /**
+     * Prints disk usage statistics about a directory related to statsd.
+     */
+    static void printDirStats(FILE* out, const char* path);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index 5846761..73e7c44 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -45,20 +45,41 @@
 
     const auto& matcher12 = output[0];
     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
-    EXPECT_EQ((int32_t)0x2010001, matcher12.mMatcher.getField());
+    EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
     EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask);
 }
 
-TEST(AtomMatcherTest, TestFilter) {
+TEST(AtomMatcherTest, TestFieldTranslation_ALL) {
     FieldMatcher matcher1;
     matcher1.set_field(10);
     FieldMatcher* child = matcher1.add_child();
     child->set_field(1);
-    child->set_position(Position::ANY);
+    child->set_position(Position::ALL);
 
     child = child->add_child();
     child->set_field(1);
 
+    vector<Matcher> output;
+    translateFieldMatcher(matcher1, &output);
+
+    EXPECT_EQ((size_t)1, output.size());
+
+    const auto& matcher12 = output[0];
+    EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
+    EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
+    EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
+}
+
+TEST(AtomMatcherTest, TestFilter_ALL) {
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+    child->set_position(Position::ALL);
+
+    child->add_child()->set_field(1);
+    child->add_child()->set_field(2);
+
     child = matcher1.add_child();
     child->set_field(2);
 
@@ -85,32 +106,28 @@
     event.write("some value");
     // Convert to a LogEvent
     event.init();
-    vector<HashableDimensionKey> output;
+    HashableDimensionKey output;
 
     filterValues(matchers, event.getValues(), &output);
 
-    EXPECT_EQ((size_t)(3), output.size());
+    EXPECT_EQ((size_t)7, output.getValues().size());
+    EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
+    EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
+    EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
+    EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
 
-    const auto& key1 = output[0];
-    EXPECT_EQ((size_t)2, key1.getValues().size());
-    EXPECT_EQ((int32_t)0x02010001, key1.getValues()[0].mField.getField());
-    EXPECT_EQ((int32_t)1111, key1.getValues()[0].mValue.int_value);
-    EXPECT_EQ((int32_t)0x00020000, key1.getValues()[1].mField.getField());
-    EXPECT_EQ("some value", key1.getValues()[1].mValue.str_value);
+    EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
+    EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
+    EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
+    EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
 
-    const auto& key2 = output[1];
-    EXPECT_EQ((size_t)2, key2.getValues().size());
-    EXPECT_EQ((int32_t)0x02010001, key2.getValues()[0].mField.getField());
-    EXPECT_EQ((int32_t)2222, key2.getValues()[0].mValue.int_value);
-    EXPECT_EQ((int32_t)0x00020000, key2.getValues()[1].mField.getField());
-    EXPECT_EQ("some value", key2.getValues()[1].mValue.str_value);
+    EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
+    EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
+    EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
+    EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
 
-    const auto& key3 = output[2];
-    EXPECT_EQ((size_t)2, key3.getValues().size());
-    EXPECT_EQ((int32_t)0x02010001, key3.getValues()[0].mField.getField());
-    EXPECT_EQ((int32_t)3333, key3.getValues()[0].mValue.int_value);
-    EXPECT_EQ((int32_t)0x00020000, key3.getValues()[1].mField.getField());
-    EXPECT_EQ("some value", key3.getValues()[1].mValue.str_value);
+    EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
+    EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
 }
 
 TEST(AtomMatcherTest, TestSubDimension) {
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 7a7e000..2574ba7 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -28,7 +28,7 @@
 
 namespace {
 
-StatsdConfig CreateStatsdConfig() {
+StatsdConfig CreateStatsdConfig(const Position position) {
     StatsdConfig config;
     auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
     auto attributionNodeMatcher =
@@ -46,15 +46,15 @@
     countMetric->set_what(wakelockAcquireMatcher.id());
     *countMetric->mutable_dimensions_in_what() =
         CreateAttributionUidAndTagDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+            android::util::WAKELOCK_STATE_CHANGED, {position});
     countMetric->set_bucket(FIVE_MINUTES);
     return config;
 }
 
 }  // namespace
 
-TEST(AttributionE2eTest, TestAttributionMatchAndSlice) {
-    auto config = CreateStatsdConfig();
+TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
+    auto config = CreateStatsdConfig(Position::FIRST);
     int64_t bucketStartTimeNs = 10000000000;
     int64_t bucketSizeNs =
         TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
@@ -199,6 +199,215 @@
     EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
 }
 
+TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
+    auto config = CreateStatsdConfig(Position::ALL);
+    int64_t bucketStartTimeNs = 10000000000;
+    int64_t bucketSizeNs =
+        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+
+    ConfigKey cfgKey;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+    // Here it assumes that GMS core has two uids.
+    processor->getUidMap()->updateApp(
+        android::String16("com.android.gmscore"), 222 /* uid */, 1 /* version code*/);
+    processor->getUidMap()->updateApp(
+        android::String16("com.android.gmscore"), 444 /* uid */, 1 /* version code*/);
+    processor->getUidMap()->updateApp(
+        android::String16("app1"), 111 /* uid */, 2 /* version code*/);
+    processor->getUidMap()->updateApp(
+        android::String16("APP3"), 333 /* uid */, 2 /* version code*/);
+
+    // GMS core node is in the middle.
+    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
+                                                          CreateAttribution(222, "GMSCoreModule1"),
+                                                          CreateAttribution(333, "App3")};
+
+    // GMS core node is the last one.
+    std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
+                                                          CreateAttribution(333, "App3"),
+                                                          CreateAttribution(222, "GMSCoreModule1")};
+
+    // GMS core node is the first one.
+    std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
+                                                          CreateAttribution(333, "App3")};
+
+    // Single GMS core node.
+    std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
+
+    // GMS core has another uid.
+    std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
+                                                          CreateAttribution(444, "GMSCoreModule2"),
+                                                          CreateAttribution(333, "App3")};
+
+    // Multiple GMS core nodes.
+    std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
+                                                          CreateAttribution(222, "GMSCoreModule1")};
+
+    // No GMS core nodes.
+    std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
+                                                          CreateAttribution(333, "App3")};
+    std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
+
+    // GMS core node with isolated uid.
+    const int isolatedUid = 666;
+    std::vector<AttributionNodeInternal> attributions9 = {
+            CreateAttribution(isolatedUid, "GMSCoreModule1")};
+
+    std::vector<std::unique_ptr<LogEvent>> events;
+    // Events 1~4 are in the 1st bucket.
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions1, "wl1", bucketStartTimeNs + 2));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions2, "wl1", bucketStartTimeNs + 200));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+
+    // Events 5~8 are in the 3rd bucket.
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+    events.push_back(CreateAcquireWakelockEvent(
+        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+    events.push_back(CreateIsolatedUidChangedEvent(
+        isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+    events.push_back(CreateIsolatedUidChangedEvent(
+        isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+
+    sortLogEventsByTimestamp(&events);
+
+    for (const auto& event : events) {
+        processor->OnLogEvent(event.get());
+    }
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, &buffer);
+    EXPECT_TRUE(buffer.size() > 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    EXPECT_EQ(reports.reports_size(), 1);
+    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+
+    StatsLogReport::CountMetricDataWrapper countMetrics;
+    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+    EXPECT_EQ(countMetrics.data_size(), 6);
+
+    auto data = countMetrics.data(0);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+    EXPECT_EQ(2, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+    EXPECT_EQ(1, data.bucket_info(1).count());
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+              data.bucket_info(1).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
+              data.bucket_info(1).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(1);
+    ValidateUidDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+    EXPECT_EQ(data.bucket_info_size(), 1);
+    EXPECT_EQ(data.bucket_info(0).count(), 1);
+    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+
+    data = countMetrics.data(2);
+    ValidateUidDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+    EXPECT_EQ(data.bucket_info_size(), 1);
+    EXPECT_EQ(data.bucket_info(0).count(), 1);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(3);
+    ValidateUidDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+    EXPECT_EQ(data.bucket_info_size(), 1);
+    EXPECT_EQ(data.bucket_info(0).count(), 1);
+    EXPECT_EQ(bucketStartTimeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(4);
+    ValidateUidDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+    EXPECT_EQ(data.bucket_info_size(), 1);
+    EXPECT_EQ(data.bucket_info(0).count(), 1);
+    EXPECT_EQ(bucketStartTimeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(5);
+    ValidateUidDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+    ValidateUidDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+    ValidateAttributionUidAndTagDimension(
+        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+    EXPECT_EQ(data.bucket_info_size(), 1);
+    EXPECT_EQ(data.bucket_info(0).count(), 1);
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+}
+
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
new file mode 100644
index 0000000..9ceffc8
--- /dev/null
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -0,0 +1,281 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateStatsdConfigForPushedEvent(const GaugeMetric::SamplingType sampling_type) {
+    StatsdConfig config;
+    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+
+    auto atomMatcher = CreateSimpleAtomMatcher("", android::util::APP_START_CHANGED);
+    *config.add_atom_matcher() = atomMatcher;
+
+    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
+    *config.add_predicate() = isInBackgroundPredicate;
+
+    auto gaugeMetric = config.add_gauge_metric();
+    gaugeMetric->set_id(123456);
+    gaugeMetric->set_what(atomMatcher.id());
+    gaugeMetric->set_condition(isInBackgroundPredicate.id());
+    gaugeMetric->mutable_gauge_fields_filter()->set_include_all(false);
+    gaugeMetric->set_sampling_type(sampling_type);
+    auto fieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields();
+    fieldMatcher->set_field(android::util::APP_START_CHANGED);
+    fieldMatcher->add_child()->set_field(3);  // type (enum)
+    fieldMatcher->add_child()->set_field(4);  // activity_name(str)
+    fieldMatcher->add_child()->set_field(7);  // activity_start_msec(int64)
+    *gaugeMetric->mutable_dimensions_in_what() =
+        CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ });
+    gaugeMetric->set_bucket(FIVE_MINUTES);
+
+    auto links = gaugeMetric->add_links();
+    links->set_condition(isInBackgroundPredicate.id());
+    auto dimensionWhat = links->mutable_fields_in_what();
+    dimensionWhat->set_field(android::util::APP_START_CHANGED);
+    dimensionWhat->add_child()->set_field(1);  // uid field.
+    auto dimensionCondition = links->mutable_fields_in_condition();
+    dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+    dimensionCondition->add_child()->set_field(1);  // uid field.
+    return config;
+}
+
+std::unique_ptr<LogEvent> CreateAppStartChangedEvent(
+    const int uid, const string& pkg_name, AppStartChanged::TransitionType type,
+    const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
+    int64_t activity_start_msec, uint64_t timestampNs) {
+    auto logEvent = std::make_unique<LogEvent>(
+        android::util::APP_START_CHANGED, timestampNs);
+    logEvent->write(uid);
+    logEvent->write(pkg_name);
+    logEvent->write(type);
+    logEvent->write(activity_name);
+    logEvent->write(calling_pkg_name);
+    logEvent->write(is_instant_app);
+    logEvent->write(activity_start_msec);
+    logEvent->init();
+    return logEvent;
+}
+
+}  // namespace
+
+TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
+    for (const auto& sampling_type :
+            { GaugeMetric::ALL_CONDITION_CHANGES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
+        auto config = CreateStatsdConfigForPushedEvent(sampling_type);
+        int64_t bucketStartTimeNs = 10000000000;
+        int64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+
+        ConfigKey cfgKey;
+        auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
+        EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+        EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+
+        int appUid1 = 123;
+        int appUid2 = 456;
+        std::vector<std::unique_ptr<LogEvent>> events;
+        events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
+        events.push_back(CreateMoveToForegroundEvent(
+                appUid1, bucketStartTimeNs + bucketSizeNs + 250));
+        events.push_back(CreateMoveToBackgroundEvent(
+                appUid1, bucketStartTimeNs + bucketSizeNs + 350));
+        events.push_back(CreateMoveToForegroundEvent(
+            appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
+
+
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::WARM, "activity_name1", "calling_pkg_name1",
+            true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::HOT, "activity_name2", "calling_pkg_name2",
+            true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::COLD, "activity_name3", "calling_pkg_name3",
+            true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::WARM, "activity_name4", "calling_pkg_name4",
+            true /*is_instant_app*/, 104 /*activity_start_msec*/,
+            bucketStartTimeNs + bucketSizeNs + 30));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::COLD, "activity_name5", "calling_pkg_name5",
+            true /*is_instant_app*/, 105 /*activity_start_msec*/,
+            bucketStartTimeNs + 2 * bucketSizeNs));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid1, "app1", AppStartChanged::HOT, "activity_name6", "calling_pkg_name6",
+            false /*is_instant_app*/, 106 /*activity_start_msec*/,
+            bucketStartTimeNs + 2 * bucketSizeNs + 10));
+
+        events.push_back(CreateMoveToBackgroundEvent(
+                appUid2, bucketStartTimeNs + bucketSizeNs + 10));
+        events.push_back(CreateAppStartChangedEvent(
+            appUid2, "app2", AppStartChanged::COLD, "activity_name7", "calling_pkg_name7",
+            true /*is_instant_app*/, 201 /*activity_start_msec*/,
+            bucketStartTimeNs + 2 * bucketSizeNs + 10));
+
+        sortLogEventsByTimestamp(&events);
+
+        for (const auto& event : events) {
+            processor->OnLogEvent(event.get());
+        }
+        ConfigMetricsReportList reports;
+        vector<uint8_t> buffer;
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer);
+        EXPECT_TRUE(buffer.size() > 0);
+        EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+        EXPECT_EQ(1, reports.reports_size());
+        EXPECT_EQ(1, reports.reports(0).metrics_size());
+        StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+        sortMetricDataByDimensionsValue(
+                reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+        EXPECT_EQ(2, gaugeMetrics.data_size());
+
+        auto data = gaugeMetrics.data(0);
+        EXPECT_EQ(android::util::APP_START_CHANGED, data.dimensions_in_what().field());
+        EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+        EXPECT_EQ(1 /* uid field */,
+                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+        EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+        EXPECT_EQ(3, data.bucket_info_size());
+        if (sampling_type == GaugeMetric::ALL_CONDITION_CHANGES) {
+            EXPECT_EQ(2, data.bucket_info(0).atom_size());
+            EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(2, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::HOT, data.bucket_info(0).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name2",
+                      data.bucket_info(0).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(102L,
+                      data.bucket_info(0).atom(0).app_start_changed().activity_start_millis());
+            EXPECT_EQ(AppStartChanged::COLD,
+                      data.bucket_info(0).atom(1).app_start_changed().type());
+            EXPECT_EQ("activity_name3",
+                      data.bucket_info(0).atom(1).app_start_changed().activity_name());
+            EXPECT_EQ(103L,
+                      data.bucket_info(0).atom(1).app_start_changed().activity_start_millis());
+
+            EXPECT_EQ(1, data.bucket_info(1).atom_size());
+            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::WARM,
+                      data.bucket_info(1).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name4",
+                      data.bucket_info(1).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(104L,
+                      data.bucket_info(1).atom(0).app_start_changed().activity_start_millis());
+
+            EXPECT_EQ(2, data.bucket_info(2).atom_size());
+            EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(2, data.bucket_info(2).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+                      data.bucket_info(2).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+                      data.bucket_info(2).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::COLD,
+                      data.bucket_info(2).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name5",
+                      data.bucket_info(2).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(105L,
+                      data.bucket_info(2).atom(0).app_start_changed().activity_start_millis());
+            EXPECT_EQ(AppStartChanged::HOT,
+                      data.bucket_info(2).atom(1).app_start_changed().type());
+            EXPECT_EQ("activity_name6",
+                      data.bucket_info(2).atom(1).app_start_changed().activity_name());
+            EXPECT_EQ(106L,
+                      data.bucket_info(2).atom(1).app_start_changed().activity_start_millis());
+        } else {
+            EXPECT_EQ(1, data.bucket_info(0).atom_size());
+            EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::HOT, data.bucket_info(0).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name2",
+                      data.bucket_info(0).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(102L,
+                      data.bucket_info(0).atom(0).app_start_changed().activity_start_millis());
+
+            EXPECT_EQ(1, data.bucket_info(1).atom_size());
+            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(1, data.bucket_info(1).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(1).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(1).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::WARM,
+                      data.bucket_info(1).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name4",
+                      data.bucket_info(1).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(104L,
+                      data.bucket_info(1).atom(0).app_start_changed().activity_start_millis());
+
+            EXPECT_EQ(1, data.bucket_info(2).atom_size());
+            EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+            EXPECT_EQ(1, data.bucket_info(2).wall_clock_timestamp_nanos_size());
+            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+                      data.bucket_info(2).start_bucket_nanos());
+            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+                      data.bucket_info(2).end_bucket_nanos());
+            EXPECT_EQ(AppStartChanged::COLD,
+                      data.bucket_info(2).atom(0).app_start_changed().type());
+            EXPECT_EQ("activity_name5",
+                      data.bucket_info(2).atom(0).app_start_changed().activity_name());
+            EXPECT_EQ(105L,
+                      data.bucket_info(2).atom(0).app_start_changed().activity_start_millis());
+        }
+
+        data = gaugeMetrics.data(1);
+
+        EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED);
+        EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+        EXPECT_EQ(1 /* uid field */,
+                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+        EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+        EXPECT_EQ(1, data.bucket_info_size());
+        EXPECT_EQ(1, data.bucket_info(0).atom_size());
+        EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+        EXPECT_EQ(1, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+        EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_nanos());
+        EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_nanos());
+        EXPECT_EQ(AppStartChanged::COLD, data.bucket_info(0).atom(0).app_start_changed().type());
+        EXPECT_EQ("activity_name7",
+                  data.bucket_info(0).atom(0).app_start_changed().activity_name());
+        EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_changed().activity_start_millis());
+    }
+}
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
deleted file mode 100644
index 3843e0a..0000000
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <gtest/gtest.h>
-
-#include "src/StatsLogProcessor.h"
-#include "src/stats_log_util.h"
-#include "tests/statsd_test_util.h"
-
-#include <vector>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-#ifdef __ANDROID__
-
-namespace {
-
-StatsdConfig CreateStatsdConfigForPushedEvent() {
-    StatsdConfig config;
-    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-
-    auto atomMatcher = CreateSimpleAtomMatcher("", android::util::APP_START_CHANGED);
-    *config.add_atom_matcher() = atomMatcher;
-
-    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
-    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
-    *config.add_predicate() = isInBackgroundPredicate;
-
-    auto gaugeMetric = config.add_gauge_metric();
-    gaugeMetric->set_id(123456);
-    gaugeMetric->set_what(atomMatcher.id());
-    gaugeMetric->set_condition(isInBackgroundPredicate.id());
-    gaugeMetric->mutable_gauge_fields_filter()->set_include_all(false);
-    auto fieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields();
-    fieldMatcher->set_field(android::util::APP_START_CHANGED);
-    fieldMatcher->add_child()->set_field(3);  // type (enum)
-    fieldMatcher->add_child()->set_field(4);  // activity_name(str)
-    fieldMatcher->add_child()->set_field(7);  // activity_start_msec(int64)
-    *gaugeMetric->mutable_dimensions_in_what() =
-        CreateDimensions(android::util::APP_START_CHANGED, {1 /* uid field */ });
-    gaugeMetric->set_bucket(FIVE_MINUTES);
-
-    auto links = gaugeMetric->add_links();
-    links->set_condition(isInBackgroundPredicate.id());
-    auto dimensionWhat = links->mutable_fields_in_what();
-    dimensionWhat->set_field(android::util::APP_START_CHANGED);
-    dimensionWhat->add_child()->set_field(1);  // uid field.
-    auto dimensionCondition = links->mutable_fields_in_condition();
-    dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
-    dimensionCondition->add_child()->set_field(1);  // uid field.
-    return config;
-}
-
-std::unique_ptr<LogEvent> CreateAppStartChangedEvent(
-    const int uid, const string& pkg_name, AppStartChanged::TransitionType type,
-    const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
-    int64_t activity_start_msec, uint64_t timestampNs) {
-    auto logEvent = std::make_unique<LogEvent>(
-        android::util::APP_START_CHANGED, timestampNs);
-    logEvent->write(uid);
-    logEvent->write(pkg_name);
-    logEvent->write(type);
-    logEvent->write(activity_name);
-    logEvent->write(calling_pkg_name);
-    logEvent->write(is_instant_app);
-    logEvent->write(activity_start_msec);
-    logEvent->init();
-    return logEvent;
-}
-
-}  // namespace
-
-TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
-    auto config = CreateStatsdConfigForPushedEvent();
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs / NS_PER_SEC, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    int appUid1 = 123;
-    int appUid2 = 456;
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
-    events.push_back(CreateMoveToForegroundEvent(appUid1, bucketStartTimeNs + bucketSizeNs + 250));
-    events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + bucketSizeNs + 350));
-    events.push_back(CreateMoveToForegroundEvent(
-        appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
-
-
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::WARM, "activity_name1", "calling_pkg_name1",
-        true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::HOT, "activity_name2", "calling_pkg_name2",
-        true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::COLD, "activity_name3", "calling_pkg_name3",
-        true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::WARM, "activity_name4", "calling_pkg_name4",
-        true /*is_instant_app*/, 104 /*activity_start_msec*/,
-        bucketStartTimeNs + bucketSizeNs + 30));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::COLD, "activity_name5", "calling_pkg_name5",
-        true /*is_instant_app*/, 105 /*activity_start_msec*/,
-        bucketStartTimeNs + 2 * bucketSizeNs));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid1, "app1", AppStartChanged::HOT, "activity_name6", "calling_pkg_name6",
-        false /*is_instant_app*/, 106 /*activity_start_msec*/,
-        bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
-    events.push_back(CreateMoveToBackgroundEvent(appUid2, bucketStartTimeNs + bucketSizeNs + 10));
-    events.push_back(CreateAppStartChangedEvent(
-        appUid2, "app2", AppStartChanged::COLD, "activity_name7", "calling_pkg_name7",
-        true /*is_instant_app*/, 201 /*activity_start_msec*/,
-        bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_EQ(gaugeMetrics.data_size(), 2);
-
-    auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid1);
-    EXPECT_EQ(data.bucket_info_size(), 3);
-    EXPECT_EQ(data.bucket_info(0).atom_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::HOT);
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name2");
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 102L);
-
-    EXPECT_EQ(data.bucket_info(1).atom_size(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().type(), AppStartChanged::WARM);
-    EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_name(), "activity_name4");
-    EXPECT_EQ(data.bucket_info(1).atom(0).app_start_changed().activity_start_millis(), 104L);
-
-    EXPECT_EQ(data.bucket_info(2).atom_size(), 1);
-    EXPECT_EQ(data.bucket_info(2).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(2).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().type(), AppStartChanged::COLD);
-    EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_name(), "activity_name5");
-    EXPECT_EQ(data.bucket_info(2).atom(0).app_start_changed().activity_start_millis(), 105L);
-
-    data = gaugeMetrics.data(1);
-
-    EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1 /* uid field */);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid2);
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).atom_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().type(), AppStartChanged::COLD);
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_name(), "activity_name7");
-    EXPECT_EQ(data.bucket_info(0).atom(0).app_start_changed().activity_start_millis(), 201L);
-}
-
-#else
-GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 77b3ace..c0cc0b6 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -112,7 +112,6 @@
     it++;
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(11L, it->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
 
     gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
     EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -125,7 +124,6 @@
     it++;
     EXPECT_EQ(INT, it->mValue.getType());
     EXPECT_EQ(25L, it->mValue.int_value);
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
 }
 
 TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
@@ -337,7 +335,6 @@
                             .mGaugeAtoms.front()
                             .mFields->begin()
                             ->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.begin()->second.back().mBucketNum);
 }
 
 TEST(GaugeMetricProducerTest, TestAnomalyDetection) {
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 2678c8a..0f785df 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -500,12 +500,42 @@
         .value_tuple().dimensions_value(0).value_int(), uid);
 }
 
+void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid) {
+    EXPECT_EQ(value.field(), atomId);
+    EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx);
+    // Attribution field.
+    EXPECT_EQ(value.value_tuple().dimensions_value(node_idx).field(), 1);
+    EXPECT_EQ(value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(0).field(), 1);
+    EXPECT_EQ(value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(0).value_int(), uid);
+}
+
+void ValidateAttributionUidAndTagDimension(
+    const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag) {
+    EXPECT_EQ(value.field(), atomId);
+    EXPECT_GT(value.value_tuple().dimensions_value_size(), node_idx);
+    // Attribution field.
+    EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx).field());
+    // Uid only.
+    EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value_size());
+    EXPECT_EQ(1, value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(uid, value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(2, value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(1).field());
+    EXPECT_EQ(tag, value.value_tuple().dimensions_value(node_idx)
+        .value_tuple().dimensions_value(1).value_str());
+}
+
 void ValidateAttributionUidAndTagDimension(
     const DimensionsValue& value, int atomId, int uid, const std::string& tag) {
     EXPECT_EQ(value.field(), atomId);
-    EXPECT_EQ(value.value_tuple().dimensions_value_size(), 1);
+    EXPECT_EQ(1, value.value_tuple().dimensions_value_size());
     // Attribution field.
-    EXPECT_EQ(value.value_tuple().dimensions_value(0).field(), 1);
+    EXPECT_EQ(1, value.value_tuple().dimensions_value(0).field());
     // Uid only.
     EXPECT_EQ(value.value_tuple().dimensions_value(0)
         .value_tuple().dimensions_value_size(), 2);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 14eba1f..1ac630c 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -180,9 +180,12 @@
 
 int64_t StringToId(const string& str);
 
+void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
 void ValidateAttributionUidDimension(const DimensionsValue& value, int atomId, int uid);
 void ValidateAttributionUidAndTagDimension(
     const DimensionsValue& value, int atomId, int uid, const std::string& tag);
+void ValidateAttributionUidAndTagDimension(
+    const DimensionsValue& value, int node_idx, int atomId, int uid, const std::string& tag);
 
 struct DimensionsPair {
     DimensionsPair(DimensionsValue m1, DimensionsValue m2) : dimInWhat(m1), dimInCondition(m2){};
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index f134e54..9f71f26 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -649,6 +649,8 @@
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/input/InputManager;->getInstance()Landroid/hardware/input/InputManager;
+Landroid/hardware/input/InputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
+Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I
 Landroid/hardware/input/InputManager;->mIm:Landroid/hardware/input/IInputManager;
 Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
 Landroid/hardware/SerialPort;->mNativeContext:I
@@ -656,6 +658,7 @@
 Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;-><init>(II)V
 Landroid/hardware/soundtrigger/SoundTrigger$ConfidenceLevel;->userId:I
 Landroid/hardware/soundtrigger/SoundTrigger$GenericRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$GenericSoundModel;-><init>(Ljava/util/UUID;Ljava/util/UUID;[B)V
 Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->id:I
 Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;->locale:Ljava/lang/String;
 Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;)V
@@ -674,6 +677,7 @@
 Landroid/hardware/soundtrigger/SoundTrigger$ModuleProperties;-><init>(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIZIZIZ)V
 Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->captureRequested:Z
 Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;-><init>(ZZ[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;[B)V
 Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
 Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
 Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
@@ -890,6 +894,10 @@
 Landroid/media/RemoteDisplay;->notifyDisplayError(I)V
 Landroid/media/RingtoneManager;->getRingtone(Landroid/content/Context;Landroid/net/Uri;I)Landroid/media/Ringtone;
 Landroid/media/session/MediaSessionLegacyHelper;->getHelper(Landroid/content/Context;)Landroid/media/session/MediaSessionLegacyHelper;
+Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
+Landroid/media/soundtrigger/SoundTriggerDetector$EventPayload;->getData()[B
+Landroid/media/soundtrigger/SoundTriggerManager;->loadSoundModel(Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;)I
+Landroid/media/soundtrigger/SoundTriggerManager;->startRecognition(Ljava/util/UUID;Landroid/app/PendingIntent;Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;)I
 Landroid/media/soundtrigger/SoundTriggerManager;->stopRecognition(Ljava/util/UUID;)I
 Landroid/media/soundtrigger/SoundTriggerManager;->unloadSoundModel(Ljava/util/UUID;)I
 Landroid/media/SubtitleController;->mHandler:Landroid/os/Handler;
@@ -1556,6 +1564,7 @@
 Landroid/service/media/MediaBrowserService$Result;->mFlags:I
 Landroid/service/notification/NotificationListenerService;->registerAsSystemService(Landroid/content/Context;Landroid/content/ComponentName;I)V
 Landroid/service/notification/NotificationListenerService;->unregisterAsSystemService()V
+Landroid/service/voice/AlwaysOnHotwordDetector$EventPayload;->getCaptureSession()Ljava/lang/Integer;
 Landroid/service/voice/VoiceInteractionService;->isKeyphraseAndLocaleSupportedForHotword(Ljava/lang/String;Ljava/util/Locale;)Z
 Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
 Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
@@ -1571,6 +1580,7 @@
 Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
 Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
 Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
+Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
 Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
 Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
 Landroid/telephony/SignalStrength;->getAsuLevel()I
@@ -1595,6 +1605,7 @@
 Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
 Landroid/telephony/SmsMessage;->getSubId()I
 Landroid/telephony/SmsMessage;->mWrappedSmsMessage:Lcom/android/internal/telephony/SmsMessageBase;
+Landroid/telephony/SubscriptionManager;->getActiveSubscriptionIdList()[I
 Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoCount()I
 Landroid/telephony/SubscriptionManager;->getAllSubscriptionInfoList()Ljava/util/List;
 Landroid/telephony/SubscriptionManager;->getDefaultDataSubscriptionInfo()Landroid/telephony/SubscriptionInfo;
@@ -1767,6 +1778,7 @@
 Landroid/view/InputDevice;->addMotionRange(IIFFFFF)V
 Landroid/view/InputDevice;-><init>(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V
 Landroid/view/InputDevice;->isExternal()Z
+Landroid/view/InputEvent;->getSequenceNumber()I
 Landroid/view/InputEventReceiver;->dispatchBatchedInputEventPending()V
 Landroid/view/InputEventReceiver;->dispatchInputEvent(ILandroid/view/InputEvent;I)V
 Landroid/view/InputEventSender;->dispatchInputEventFinished(IZ)V
@@ -1885,6 +1897,7 @@
 Landroid/view/View;->clearAccessibilityFocus()V
 Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z
 Landroid/view/View;->computeOpaqueFlags()V
+Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
 Landroid/view/ViewConfiguration;->mFadingMarqueeEnabled:Z
 Landroid/view/ViewConfiguration;->sHasPermanentMenuKeySet:Z
 Landroid/view/ViewConfiguration;->sHasPermanentMenuKey:Z
@@ -2280,6 +2293,7 @@
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setContactUri(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setFeatureTag(Ljava/lang/String;)V
 Lcom/android/ims/internal/uce/presence/PresTupleInfo;->setTimestamp(Ljava/lang/String;)V
+Lcom/android/internal/app/AlertController$RecycleListView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Lcom/android/internal/app/IAppOpsService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IAppOpsService;
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -2500,7 +2514,13 @@
 Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
 Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
 Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;
+Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String;
 Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
+Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest:Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->networkRequest(Lcom/android/okhttp/Request;)Lcom/android/okhttp/Request;
+Lcom/android/okhttp/internal/http/HttpEngine;->priorResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response;
 Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool;
 Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List;
 Lcom/android/okhttp/OkHttpClient;->dns:Lcom/android/okhttp/Dns;
@@ -2508,6 +2528,14 @@
 Lcom/android/okhttp/OkHttpClient;->setRetryOnConnectionFailure(Z)V
 Lcom/android/okhttp/okio/ByteString;->readObject(Ljava/io/ObjectInputStream;)V
 Lcom/android/okhttp/okio/ByteString;->writeObject(Ljava/io/ObjectOutputStream;)V
+Lcom/android/okhttp/Request;->headers:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Request;->method:Ljava/lang/String;
+Lcom/android/okhttp/Request;->url:Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/Response;->code:I
+Lcom/android/okhttp/Response;->headers:Lcom/android/okhttp/Headers;
+Lcom/android/okhttp/Response;->message:Ljava/lang/String;
+Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
+Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String;
 Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 05a9861..14edd31 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1609,6 +1609,7 @@
      * @param mode The app op mode to set.
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(int code, int uid, int mode) {
         try {
             mService.setUidMode(code, uid, mode);
@@ -1628,7 +1629,7 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS)
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(String appOp, int uid, int mode) {
         try {
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
@@ -1660,6 +1661,7 @@
 
     /** @hide */
     @TestApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setMode(int code, int uid, String packageName, int mode) {
         try {
             mService.setMode(code, uid, packageName, mode);
@@ -1669,6 +1671,27 @@
     }
 
     /**
+     * Change the operating mode for the given op in the given app package.  You must pass
+     * in both the uid and name of the application whose mode is being modified; if these
+     * do not match, the modification will not be applied.
+     *
+     * @param op The operation to modify.  One of the OPSTR_* constants.
+     * @param uid The user id of the application whose mode will be changed.
+     * @param packageName The name of the application package name whose mode will
+     * be changed.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
+    public void setMode(String op, int uid, String packageName, int mode) {
+        try {
+            mService.setMode(strOpToOp(op), uid, packageName, mode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Set a non-persisted restriction on an audio operation at a stream-level.
      * Restrictions are temporary additional constraints imposed on top of the persisted rules
      * defined by {@link #setMode}.
@@ -1679,6 +1702,7 @@
      * @param exceptionPackages Optional list of packages to exclude from the restriction.
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setRestriction(int code, @AttributeUsage int usage, int mode,
             String[] exceptionPackages) {
         try {
@@ -1690,6 +1714,7 @@
     }
 
     /** @hide */
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void resetAllModes() {
         try {
             mService.resetAllModes(mContext.getUserId(), null);
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 41eeb9a..4531f53 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -16,8 +16,6 @@
 
 package android.app;
 
-import java.util.ArrayList;
-
 import android.annotation.CallSuper;
 import android.content.ComponentCallbacks;
 import android.content.ComponentCallbacks2;
@@ -26,8 +24,11 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.autofill.AutofillManager;
 
+import java.util.ArrayList;
+
 /**
  * Base class for maintaining global application state. You can provide your own
  * implementation by creating a subclass and specifying the fully-qualified name
@@ -46,6 +47,7 @@
  * </p>
  */
 public class Application extends ContextWrapper implements ComponentCallbacks2 {
+    private static final String TAG = "Application";
     private ArrayList<ComponentCallbacks> mComponentCallbacks =
             new ArrayList<ComponentCallbacks>();
     private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
@@ -318,6 +320,9 @@
         if (client != null) {
             return client;
         }
+        if (android.view.autofill.Helper.sVerbose) {
+            Log.v(TAG, "getAutofillClient(): null on super, trying to find activity thread");
+        }
         // Okay, ppl use the application context when they should not. This breaks
         // autofill among other things. We pick the focused activity since autofill
         // interacts only with the currently focused activity and we need the fill
@@ -338,9 +343,16 @@
                 continue;
             }
             if (activity.getWindow().getDecorView().hasFocus()) {
-                return record.activity;
+                if (android.view.autofill.Helper.sVerbose) {
+                    Log.v(TAG, "getAutofillClient(): found activity for " + this + ": " + activity);
+                }
+                return activity;
             }
         }
+        if (android.view.autofill.Helper.sVerbose) {
+            Log.v(TAG, "getAutofillClient(): none of the " + activityCount + " activities on "
+                    + this + " have focus");
+        }
         return null;
     }
 }
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 9e9a9c5..0d995e8 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -147,7 +147,10 @@
             pw.println("Executor:");
             dump(pw, prefix);
 
-            Slog.wtf(TAG, stringWriter.toString());
+            Slog.w(TAG, stringWriter.toString());
+
+            // Ignore requests for non-existent client records for now.
+            return;
         }
 
         // Cycle to the state right before the final requested state.
diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl
index 20ec75a..74e3c3e 100644
--- a/core/java/android/app/slice/ISliceManager.aidl
+++ b/core/java/android/app/slice/ISliceManager.aidl
@@ -27,6 +27,7 @@
     SliceSpec[] getPinnedSpecs(in Uri uri, String pkg);
     int checkSlicePermission(in Uri uri, String pkg, int pid, int uid);
     void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices);
+    Uri[] getPinnedSlices(String pkg);
 
     byte[] getBackupPayload(int user);
     void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 4f3cd63..c5ea9b2 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -184,6 +184,18 @@
     }
 
     /**
+     * Get the list of currently pinned slices for this app.
+     * @see SliceProvider#onSlicePinned
+     */
+    public @NonNull List<Uri> getPinnedSlices() {
+        try {
+            return Arrays.asList(mService.getPinnedSlices(mContext.getPackageName()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Obtains a list of slices that are descendants of the specified Uri.
      * <p>
      * Not all slice providers will implement this functionality, in which case,
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index f7fb84b..4c7e97b 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -109,11 +109,11 @@
         public static final int NOTIFICATION_SEEN = 10;
 
         /**
-         * An event type denoting a change in App Standby Bucket. Additional bucket information
-         * is contained in mBucketAndReason.
-         * @hide
+         * An event type denoting a change in App Standby Bucket. The new bucket can be
+         * retrieved by calling {@link #getStandbyBucket()}.
+         *
+         * @see UsageStatsManager#getAppStandbyBucket()
          */
-        @SystemApi
         public static final int STANDBY_BUCKET_CHANGED = 11;
 
         /**
@@ -254,8 +254,11 @@
         /**
          * The event type.
          *
-         * See {@link #MOVE_TO_BACKGROUND}
-         * See {@link #MOVE_TO_FOREGROUND}
+         * @see #MOVE_TO_BACKGROUND
+         * @see #MOVE_TO_FOREGROUND
+         * @see #CONFIGURATION_CHANGE
+         * @see #USER_INTERACTION
+         * @see #STANDBY_BUCKET_CHANGED
          */
         public int getEventType() {
             return mEventType;
@@ -283,9 +286,8 @@
          * Returns the standby bucket of the app, if the event is of type
          * {@link #STANDBY_BUCKET_CHANGED}, otherwise returns 0.
          * @return the standby bucket associated with the event.
-         * @hide
+         *
          */
-        @SystemApi
         public int getStandbyBucket() {
             return (mBucketAndReason & 0xFFFF0000) >>> 16;
         }
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 10331d4..ce7d3af 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2143,21 +2143,6 @@
     }
 
     /**
-     * @hide
-     */
-    public void releasePersistableUriPermission(@NonNull String toPackage, @NonNull Uri uri,
-            @Intent.AccessUriMode int modeFlags) {
-        Preconditions.checkNotNull(toPackage, "toPackage");
-        Preconditions.checkNotNull(uri, "uri");
-        try {
-            ActivityManager.getService().releasePersistableUriPermission(
-                    ContentProvider.getUriWithoutUserId(uri), modeFlags, toPackage,
-                    resolveUserId(uri));
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
      * Return list of all URI permission grants that have been persisted by the
      * calling app. That is, the returned permissions have been granted
      * <em>to</em> the calling app. Only persistable grants taken with
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index efa90d3..387a836 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1188,7 +1188,7 @@
             if (category != CATEGORY_UNDEFINED) {
                 pw.println(prefix + "category=" + category);
             }
-            pw.println("isAllowedToUseHiddenApi=" + isAllowedToUseHiddenApi());
+            pw.println(prefix + "isAllowedToUseHiddenApi=" + isAllowedToUseHiddenApi());
         }
         super.dumpBack(pw, prefix);
     }
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 5b3d3e5..6feb170 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -451,6 +451,9 @@
     /** Whether the binder caller can access instant apps. */
     public abstract boolean canAccessInstantApps(int callingUid, int userId);
 
+    /** Whether the binder caller can access the given component. */
+    public abstract boolean canAccessComponent(int callingUid, ComponentName component, int userId);
+
     /**
      * Returns {@code true} if a given package has instant application meta-data.
      * Otherwise, returns {@code false}. Meta-data is state (eg. cookie, app icon, etc)
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index f47d464..72db33f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -819,8 +819,7 @@
      * @param config A session configuration (see {@link SessionConfiguration}).
      *
      * @throws IllegalArgumentException In case the session configuration is invalid; or the output
-     *                                  configurations are empty; or the session configuration
-     *                                  executor is invalid.
+     *                                  configurations are empty.
      * @throws CameraAccessException In case the camera device is no longer connected or has
      *                               encountered a fatal error.
      * @see #createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)
diff --git a/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java
new file mode 100644
index 0000000..866f370
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * A dispatcher that replaces one argument with another; replaces any argument at an index
+ * with another argument.
+ *
+ * <p>For example, we can override an {@code void onSomething(int x)} calls to have {@code x} always
+ * equal to 1. Or, if using this with a duck typing dispatcher, we could even overwrite {@code x} to
+ * be something
+ * that's not an {@code int}.</p>
+ *
+ * @param <T>
+ *          source dispatch type, whose methods with {@link #dispatch} will be called
+ * @param <TArg>
+ *          argument replacement type, args in {@link #dispatch} matching {@code argumentIndex}
+ *          will be overriden to objects of this type
+ */
+public class ArgumentReplacingDispatcher<T, TArg> implements Dispatchable<T> {
+
+    private final Dispatchable<T> mTarget;
+    private final int mArgumentIndex;
+    private final TArg mReplaceWith;
+
+    /**
+     * Create a new argument replacing dispatcher; dispatches are forwarded to {@code target}
+     * after the argument is replaced.
+     *
+     * <p>For example, if a method {@code onAction(T1 a, Integer b, T2 c)} is invoked, and we wanted
+     * to replace all occurrences of {@code b} with {@code 0xDEADBEEF}, we would set
+     * {@code argumentIndex = 1} and {@code replaceWith = 0xDEADBEEF}.</p>
+     *
+     * <p>If a method dispatched has less arguments than {@code argumentIndex}, it is
+     * passed through with the arguments unchanged.</p>
+     *
+     * @param target destination dispatch type, methods will be redirected to this dispatcher
+     * @param argumentIndex the numeric index of the argument {@code >= 0}
+     * @param replaceWith arguments matching {@code argumentIndex} will be replaced with this object
+     */
+    public ArgumentReplacingDispatcher(Dispatchable<T> target, int argumentIndex,
+            TArg replaceWith) {
+        mTarget = checkNotNull(target, "target must not be null");
+        mArgumentIndex = checkArgumentNonnegative(argumentIndex,
+                "argumentIndex must not be negative");
+        mReplaceWith = checkNotNull(replaceWith, "replaceWith must not be null");
+    }
+
+    @Override
+    public Object dispatch(Method method, Object[] args) throws Throwable {
+
+        if (args.length > mArgumentIndex) {
+            args = arrayCopy(args); // don't change in-place since it can affect upstream dispatches
+            args[mArgumentIndex] = mReplaceWith;
+        }
+
+        return mTarget.dispatch(method, args);
+    }
+
+    private static Object[] arrayCopy(Object[] array) {
+        int length = array.length;
+        Object[] newArray = new Object[length];
+        for (int i = 0; i < length; ++i) {
+            newArray[i] = array[i];
+        }
+        return newArray;
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java
new file mode 100644
index 0000000..fe575b2
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Broadcast a single dispatch into multiple other dispatchables.
+ *
+ * <p>Every time {@link #dispatch} is invoked, all the broadcast targets will
+ * see the same dispatch as well. The first target's return value is returned.</p>
+ *
+ * <p>This enables a single listener to be converted into a multi-listener.</p>
+ */
+public class BroadcastDispatcher<T> implements Dispatchable<T> {
+
+    private final List<Dispatchable<T>> mDispatchTargets;
+
+    /**
+     * Create a broadcast dispatcher from the supplied dispatch targets.
+     *
+     * @param dispatchTargets one or more targets to dispatch to
+     */
+    @SafeVarargs
+    public BroadcastDispatcher(Dispatchable<T>... dispatchTargets) {
+        mDispatchTargets = Arrays.asList(
+                checkNotNull(dispatchTargets, "dispatchTargets must not be null"));
+    }
+
+    @Override
+    public Object dispatch(Method method, Object[] args) throws Throwable {
+        Object result = null;
+        boolean gotResult = false;
+
+        for (Dispatchable<T> dispatchTarget : mDispatchTargets) {
+            Object localResult = dispatchTarget.dispatch(method, args);
+
+            if (!gotResult) {
+                gotResult = true;
+                result = localResult;
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/Dispatchable.java b/core/java/android/hardware/camera2/dispatch/Dispatchable.java
new file mode 100644
index 0000000..753103f
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/Dispatchable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+import java.lang.reflect.Method;
+
+/**
+ * Dynamically dispatch a method and its argument to some object.
+ *
+ * <p>This can be used to intercept method calls and do work around them, redirect work,
+ * or block calls entirely.</p>
+ */
+public interface Dispatchable<T> {
+    /**
+     * Dispatch the method and arguments to this object.
+     * @param method a method defined in class {@code T}
+     * @param args arguments corresponding to said {@code method}
+     * @return the object returned when invoking {@code method}
+     * @throws Throwable any exception that might have been raised while invoking the method
+     */
+    public Object dispatch(Method method, Object[] args) throws Throwable;
+}
diff --git a/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java
new file mode 100644
index 0000000..75f97e4
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Duck typing dispatcher; converts dispatch methods calls from one class to another by
+ * looking up equivalently methods at runtime by name.
+ *
+ * <p>For example, if two types have identical method names and arguments, but
+ * are not subclasses/subinterfaces of each other, this dispatcher will allow calls to be
+ * made from one type to the other.</p>
+ *
+ * @param <TFrom> source dispatch type, whose methods with {@link #dispatch} will be called
+ * @param <T> destination dispatch type, methods will be converted to the class of {@code T}
+ */
+public class DuckTypingDispatcher<TFrom, T> implements Dispatchable<TFrom> {
+
+    private final MethodNameInvoker<T> mDuck;
+
+    /**
+     * Create a new duck typing dispatcher.
+     *
+     * @param target destination dispatch type, methods will be redirected to this dispatcher
+     * @param targetClass destination dispatch class, methods will be converted to this class's
+     */
+    public DuckTypingDispatcher(Dispatchable<T> target, Class<T> targetClass) {
+        checkNotNull(targetClass, "targetClass must not be null");
+        checkNotNull(target, "target must not be null");
+
+        mDuck = new MethodNameInvoker<T>(target, targetClass);
+    }
+
+    @Override
+    public Object dispatch(Method method, Object[] args) {
+        return mDuck.invoke(method.getName(), args);
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java
new file mode 100644
index 0000000..f8e9d49
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+import android.os.Handler;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Forward all interface calls into a handler by posting it as a {@code Runnable}.
+ *
+ * <p>All calls will return immediately; functions with return values will return a default
+ * value of {@code null}, {@code 0}, or {@code false} where that value is legal.</p>
+ *
+ * <p>Any exceptions thrown on the handler while trying to invoke a method
+ * will be re-thrown. Throwing checked exceptions on a handler which doesn't expect any
+ * checked exceptions to be thrown will result in "undefined" behavior
+ * (although in practice it is usually thrown as normal).</p>
+ */
+public class HandlerDispatcher<T> implements Dispatchable<T> {
+
+    private static final String TAG = "HandlerDispatcher";
+
+    private final Dispatchable<T> mDispatchTarget;
+    private final Handler mHandler;
+
+    /**
+     * Create a dispatcher that forwards it's dispatch calls by posting
+     * them onto the {@code handler} as a {@code Runnable}.
+     *
+     * @param dispatchTarget the destination whose method calls will be redirected into the handler
+     * @param handler all calls into {@code dispatchTarget} will be posted onto this handler
+     * @param <T> the type of the element you want to wrap.
+     * @return a dispatcher that will forward it's dispatch calls to a handler
+     */
+    public HandlerDispatcher(Dispatchable<T> dispatchTarget, Handler handler) {
+        mDispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+        mHandler = checkNotNull(handler, "handler must not be null");
+    }
+
+    @Override
+    public Object dispatch(final Method method, final Object[] args) throws Throwable {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mDispatchTarget.dispatch(method, args);
+                } catch (InvocationTargetException e) {
+                    Throwable t = e.getTargetException();
+                    // Potential UB. Hopefully 't' is a runtime exception.
+                    UncheckedThrow.throwAnyException(t);
+                } catch (IllegalAccessException e) {
+                    // Impossible
+                    Log.wtf(TAG, "IllegalAccessException while invoking " + method, e);
+                } catch (IllegalArgumentException e) {
+                    // Impossible
+                    Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e);
+                } catch (Throwable e) {
+                    UncheckedThrow.throwAnyException(e);
+                }
+            }
+        });
+
+        // TODO handle primitive return values that would avoid NPE if unboxed
+        return null;
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java
new file mode 100644
index 0000000..ac5f526
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+
+public class InvokeDispatcher<T> implements Dispatchable<T> {
+
+    private static final String TAG = "InvocationSink";
+    private final T mTarget;
+
+    public InvokeDispatcher(T target) {
+        mTarget = checkNotNull(target, "target must not be null");
+    }
+
+    @Override
+    public Object dispatch(Method method, Object[] args) {
+        try {
+            return method.invoke(mTarget, args);
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            // Potential UB. Hopefully 't' is a runtime exception.
+            UncheckedThrow.throwAnyException(t);
+        } catch (IllegalAccessException e) {
+            // Impossible
+            Log.wtf(TAG, "IllegalAccessException while invoking " + method, e);
+        } catch (IllegalArgumentException e) {
+            // Impossible
+            Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e);
+        }
+
+        // unreachable
+        return null;
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
new file mode 100644
index 0000000..8296b7a
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Invoke a method on a dispatchable by its name (without knowing the {@code Method} ahead of time).
+ *
+ * @param <T> destination dispatch type, methods will be looked up in the class of {@code T}
+ */
+public class MethodNameInvoker<T> {
+
+    private final Dispatchable<T> mTarget;
+    private final Class<T> mTargetClass;
+    private final Method[] mTargetClassMethods;
+    private final ConcurrentHashMap<String, Method> mMethods =
+            new ConcurrentHashMap<>();
+
+    /**
+     * Create a new method name invoker.
+     *
+     * @param target destination dispatch type, invokes will be redirected to this dispatcher
+     * @param targetClass destination dispatch class, the invoked methods will be from this class
+     */
+    public MethodNameInvoker(Dispatchable<T> target, Class<T> targetClass) {
+        mTargetClass = targetClass;
+        mTargetClassMethods = targetClass.getMethods();
+        mTarget = target;
+    }
+
+    /**
+     * Invoke a method by its name.
+     *
+     * <p>If more than one method exists in {@code targetClass}, the first method with the right
+     * number of arguments will be used, and later calls will all use that method.</p>
+     *
+     * @param methodName
+     *          The name of the method, which will be matched 1:1 to the destination method
+     * @param params
+     *          Variadic parameter list.
+     * @return
+     *          The same kind of value that would normally be returned by calling {@code methodName}
+     *          statically.
+     *
+     * @throws IllegalArgumentException if {@code methodName} does not exist on the target class
+     * @throws Throwable will rethrow anything that the target method would normally throw
+     */
+    @SuppressWarnings("unchecked")
+    public <K> K invoke(String methodName, Object... params) {
+        checkNotNull(methodName, "methodName must not be null");
+
+        Method targetMethod = mMethods.get(methodName);
+        if (targetMethod == null) {
+            for (Method method : mTargetClassMethods) {
+                // TODO future: match types of params if possible
+                if (method.getName().equals(methodName) &&
+                        (params.length == method.getParameterTypes().length) ) {
+                    targetMethod = method;
+                    mMethods.put(methodName, targetMethod);
+                    break;
+                }
+            }
+
+            if (targetMethod == null) {
+                throw new IllegalArgumentException(
+                        "Method " + methodName + " does not exist on class " + mTargetClass);
+            }
+        }
+
+        try {
+            return (K) mTarget.dispatch(targetMethod, params);
+        } catch (Throwable e) {
+            UncheckedThrow.throwAnyException(e);
+            // unreachable
+            return null;
+        }
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/NullDispatcher.java b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java
new file mode 100644
index 0000000..fada075
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+
+/**
+ * Do nothing when dispatching; follows the null object pattern.
+ */
+public class NullDispatcher<T> implements Dispatchable<T> {
+    /**
+     * Create a dispatcher that does nothing when dispatched to.
+     */
+    public NullDispatcher() {
+    }
+
+    /**
+     * Do nothing; all parameters are ignored.
+     */
+    @Override
+    public Object dispatch(Method method, Object[] args) {
+        return null;
+    }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/package.html b/core/java/android/hardware/camera2/dispatch/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/hardware/camera2/impl/CallbackProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java
index 9e4cb80..c9eecf1 100644
--- a/core/java/android/hardware/camera2/impl/CallbackProxies.java
+++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java
@@ -15,17 +15,16 @@
  */
 package android.hardware.camera2.impl;
 
-import android.os.Binder;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.dispatch.Dispatchable;
+import android.hardware.camera2.dispatch.MethodNameInvoker;
 import android.view.Surface;
 
-import java.util.concurrent.Executor;
-
 import static com.android.internal.util.Preconditions.*;
 
 /**
@@ -35,86 +34,164 @@
  * to use our own proxy mechanism.</p>
  */
 public class CallbackProxies {
+
+    // TODO: replace with codegen
+
+    public static class DeviceStateCallbackProxy extends CameraDeviceImpl.StateCallbackKK {
+        private final MethodNameInvoker<CameraDeviceImpl.StateCallbackKK> mProxy;
+
+        public DeviceStateCallbackProxy(
+                Dispatchable<CameraDeviceImpl.StateCallbackKK> dispatchTarget) {
+            dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateCallbackKK.class);
+        }
+
+        @Override
+        public void onOpened(CameraDevice camera) {
+            mProxy.invoke("onOpened", camera);
+        }
+
+        @Override
+        public void onDisconnected(CameraDevice camera) {
+            mProxy.invoke("onDisconnected", camera);
+        }
+
+        @Override
+        public void onError(CameraDevice camera, int error) {
+            mProxy.invoke("onError", camera, error);
+        }
+
+        @Override
+        public void onUnconfigured(CameraDevice camera) {
+            mProxy.invoke("onUnconfigured", camera);
+        }
+
+        @Override
+        public void onActive(CameraDevice camera) {
+            mProxy.invoke("onActive", camera);
+        }
+
+        @Override
+        public void onBusy(CameraDevice camera) {
+            mProxy.invoke("onBusy", camera);
+        }
+
+        @Override
+        public void onClosed(CameraDevice camera) {
+            mProxy.invoke("onClosed", camera);
+        }
+
+        @Override
+        public void onIdle(CameraDevice camera) {
+            mProxy.invoke("onIdle", camera);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public static class DeviceCaptureCallbackProxy implements CameraDeviceImpl.CaptureCallback {
+        private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy;
+
+        public DeviceCaptureCallbackProxy(
+                Dispatchable<CameraDeviceImpl.CaptureCallback> dispatchTarget) {
+            dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+            mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureCallback.class);
+        }
+
+        @Override
+        public void onCaptureStarted(CameraDevice camera,
+                CaptureRequest request, long timestamp, long frameNumber) {
+            mProxy.invoke("onCaptureStarted", camera, request, timestamp, frameNumber);
+        }
+
+        @Override
+        public void onCapturePartial(CameraDevice camera,
+                CaptureRequest request, CaptureResult result) {
+            mProxy.invoke("onCapturePartial", camera, request, result);
+        }
+
+        @Override
+        public void onCaptureProgressed(CameraDevice camera,
+                CaptureRequest request, CaptureResult partialResult) {
+            mProxy.invoke("onCaptureProgressed", camera, request, partialResult);
+        }
+
+        @Override
+        public void onCaptureCompleted(CameraDevice camera,
+                CaptureRequest request, TotalCaptureResult result) {
+            mProxy.invoke("onCaptureCompleted", camera, request, result);
+        }
+
+        @Override
+        public void onCaptureFailed(CameraDevice camera,
+                CaptureRequest request, CaptureFailure failure) {
+            mProxy.invoke("onCaptureFailed", camera, request, failure);
+        }
+
+        @Override
+        public void onCaptureSequenceCompleted(CameraDevice camera,
+                int sequenceId, long frameNumber) {
+            mProxy.invoke("onCaptureSequenceCompleted", camera, sequenceId, frameNumber);
+        }
+
+        @Override
+        public void onCaptureSequenceAborted(CameraDevice camera,
+                int sequenceId) {
+            mProxy.invoke("onCaptureSequenceAborted", camera, sequenceId);
+        }
+
+        @Override
+        public void onCaptureBufferLost(CameraDevice camera,
+                CaptureRequest request, Surface target, long frameNumber) {
+            mProxy.invoke("onCaptureBufferLost", camera, request, target, frameNumber);
+        }
+
+    }
+
     public static class SessionStateCallbackProxy
             extends CameraCaptureSession.StateCallback {
-        private final Executor mExecutor;
-        private final CameraCaptureSession.StateCallback mCallback;
+        private final MethodNameInvoker<CameraCaptureSession.StateCallback> mProxy;
 
-        public SessionStateCallbackProxy(Executor executor,
-                CameraCaptureSession.StateCallback callback) {
-            mExecutor = checkNotNull(executor, "executor must not be null");
-            mCallback = checkNotNull(callback, "callback must not be null");
+        public SessionStateCallbackProxy(
+                Dispatchable<CameraCaptureSession.StateCallback> dispatchTarget) {
+            dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+            mProxy = new MethodNameInvoker<>(dispatchTarget,
+                    CameraCaptureSession.StateCallback.class);
         }
 
         @Override
         public void onConfigured(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onConfigured(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onConfigured", session);
         }
 
 
         @Override
         public void onConfigureFailed(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onConfigureFailed(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onConfigureFailed", session);
         }
 
         @Override
         public void onReady(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onReady(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onReady", session);
         }
 
         @Override
         public void onActive(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onActive(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onActive", session);
         }
 
         @Override
         public void onCaptureQueueEmpty(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onCaptureQueueEmpty(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onCaptureQueueEmpty", session);
         }
 
         @Override
         public void onClosed(CameraCaptureSession session) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onClosed(session));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onClosed", session);
         }
 
         @Override
         public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                mExecutor.execute(() -> mCallback.onSurfacePrepared(session, surface));
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            mProxy.invoke("onSurfacePrepared", session, surface);
         }
 
     }
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index f3f6c84..8b8bbc3 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -20,18 +20,20 @@
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.dispatch.ArgumentReplacingDispatcher;
+import android.hardware.camera2.dispatch.BroadcastDispatcher;
+import android.hardware.camera2.dispatch.DuckTypingDispatcher;
+import android.hardware.camera2.dispatch.HandlerDispatcher;
+import android.hardware.camera2.dispatch.InvokeDispatcher;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.utils.TaskDrainer;
 import android.hardware.camera2.utils.TaskSingleDrainer;
-import android.os.Binder;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.util.Log;
 import android.view.Surface;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.Executor;
 
 import static android.hardware.camera2.impl.CameraDeviceImpl.checkHandler;
 import static com.android.internal.util.Preconditions.*;
@@ -49,11 +51,11 @@
     private final Surface mInput;
     /**
      * User-specified state callback, used for outgoing events; calls to this object will be
-     * automatically invoked via {@code mStateExecutor}.
+     * automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}.
      */
     private final CameraCaptureSession.StateCallback mStateCallback;
-    /** User-specified state executor used for outgoing state callback events */
-    private final Executor mStateExecutor;
+    /** User-specified state handler used for outgoing state callback events */
+    private final Handler mStateHandler;
 
     /** Internal camera device; used to translate calls into existing deprecated API */
     private final android.hardware.camera2.impl.CameraDeviceImpl mDeviceImpl;
@@ -85,7 +87,7 @@
      * (e.g. no pending captures, no repeating requests, no flush).</p>
      */
     CameraCaptureSessionImpl(int id, Surface input,
-            CameraCaptureSession.StateCallback callback, Executor stateExecutor,
+            CameraCaptureSession.StateCallback callback, Handler stateHandler,
             android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
             Handler deviceStateHandler, boolean configureSuccess) {
         if (callback == null) {
@@ -96,8 +98,8 @@
         mIdString = String.format("Session %d: ", mId);
 
         mInput = input;
-        mStateExecutor = checkNotNull(stateExecutor, "stateExecutor must not be null");
-        mStateCallback = createUserStateCallbackProxy(mStateExecutor, callback);
+        mStateHandler = checkHandler(stateHandler);
+        mStateCallback = createUserStateCallbackProxy(mStateHandler, callback);
 
         mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null");
         mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null");
@@ -108,12 +110,12 @@
          * This ensures total ordering between CameraDevice.StateCallback and
          * CameraDeviceImpl.CaptureCallback events.
          */
-        mSequenceDrainer = new TaskDrainer<>(new HandlerExecutor(mDeviceHandler),
-                new SequenceDrainListener(), /*name*/"seq");
-        mIdleDrainer = new TaskSingleDrainer(new HandlerExecutor(mDeviceHandler),
-                new IdleDrainListener(), /*name*/"idle");
-        mAbortDrainer = new TaskSingleDrainer(new HandlerExecutor(mDeviceHandler),
-                new AbortDrainListener(), /*name*/"abort");
+        mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(),
+                /*name*/"seq");
+        mIdleDrainer = new TaskSingleDrainer(mDeviceHandler, new IdleDrainListener(),
+                /*name*/"idle");
+        mAbortDrainer = new TaskSingleDrainer(mDeviceHandler, new AbortDrainListener(),
+                /*name*/"abort");
 
         // CameraDevice should call configureOutputs and have it finish before constructing us
 
@@ -444,140 +446,114 @@
     }
 
     /**
-     * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code executor}.
+     * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code handler}.
      */
-    private StateCallback createUserStateCallbackProxy(Executor executor, StateCallback callback) {
-        return new CallbackProxies.SessionStateCallbackProxy(executor, callback);
+    private StateCallback createUserStateCallbackProxy(Handler handler, StateCallback callback) {
+        InvokeDispatcher<StateCallback> userCallbackSink = new InvokeDispatcher<>(callback);
+        HandlerDispatcher<StateCallback> handlerPassthrough =
+                new HandlerDispatcher<>(userCallbackSink, handler);
+
+        return new CallbackProxies.SessionStateCallbackProxy(handlerPassthrough);
     }
 
     /**
      * Forward callbacks from
      * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
      *
+     * <p>In particular, all calls are automatically split to go both to our own
+     * internal callback, and to the user-specified callback (by transparently posting
+     * to the user-specified handler).</p>
+     *
      * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
      */
     @SuppressWarnings("deprecation")
     private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
             Handler handler, CaptureCallback callback) {
-        final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler(
-                handler) : null;
+        CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() {
 
-        return new CameraDeviceImpl.CaptureCallback() {
             @Override
             public void onCaptureStarted(CameraDevice camera,
                     CaptureRequest request, long timestamp, long frameNumber) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureStarted(
-                                    CameraCaptureSessionImpl.this, request, timestamp,
-                                    frameNumber));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
 
             @Override
             public void onCapturePartial(CameraDevice camera,
                     CaptureRequest request, android.hardware.camera2.CaptureResult result) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCapturePartial(
-                                    CameraCaptureSessionImpl.this, request, result));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
 
             @Override
             public void onCaptureProgressed(CameraDevice camera,
                     CaptureRequest request, android.hardware.camera2.CaptureResult partialResult) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureProgressed(
-                                    CameraCaptureSessionImpl.this, request, partialResult));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
 
             @Override
             public void onCaptureCompleted(CameraDevice camera,
                     CaptureRequest request, android.hardware.camera2.TotalCaptureResult result) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureCompleted(
-                                    CameraCaptureSessionImpl.this, request, result));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
 
             @Override
             public void onCaptureFailed(CameraDevice camera,
                     CaptureRequest request, android.hardware.camera2.CaptureFailure failure) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureFailed(
-                                    CameraCaptureSessionImpl.this, request, failure));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
 
             @Override
             public void onCaptureSequenceCompleted(CameraDevice camera,
                     int sequenceId, long frameNumber) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureSequenceCompleted(
-                                    CameraCaptureSessionImpl.this, sequenceId, frameNumber));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
                 finishPendingSequence(sequenceId);
             }
 
             @Override
             public void onCaptureSequenceAborted(CameraDevice camera,
                     int sequenceId) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureSequenceAborted(
-                                    CameraCaptureSessionImpl.this, sequenceId));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
                 finishPendingSequence(sequenceId);
             }
 
             @Override
             public void onCaptureBufferLost(CameraDevice camera,
                     CaptureRequest request, Surface target, long frameNumber) {
-                if ((callback != null) && (executor != null)) {
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> callback.onCaptureBufferLost(
-                                    CameraCaptureSessionImpl.this, request, target, frameNumber));
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
-                }
+                // Do nothing
             }
+
         };
+
+        /*
+         * Split the calls from the device callback into local callback and the following chain:
+         * - replace the first CameraDevice arg with a CameraCaptureSession
+         * - duck type from device callback to session callback
+         * - then forward the call to a handler
+         * - then finally invoke the destination method on the session callback object
+         */
+        if (callback == null) {
+            // OK: API allows the user to not specify a callback, and the handler may
+            // also be null in that case. Collapse whole dispatch chain to only call the local
+            // callback
+            return localCallback;
+        }
+
+        InvokeDispatcher<CameraDeviceImpl.CaptureCallback> localSink =
+                new InvokeDispatcher<>(localCallback);
+
+        InvokeDispatcher<CaptureCallback> userCallbackSink =
+                new InvokeDispatcher<>(callback);
+        HandlerDispatcher<CaptureCallback> handlerPassthrough =
+                new HandlerDispatcher<>(userCallbackSink, handler);
+        DuckTypingDispatcher<CameraDeviceImpl.CaptureCallback, CaptureCallback> duckToSession
+                = new DuckTypingDispatcher<>(handlerPassthrough, CaptureCallback.class);
+        ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureCallback, CameraCaptureSessionImpl>
+                replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession,
+                        /*argumentIndex*/0, this);
+
+        BroadcastDispatcher<CameraDeviceImpl.CaptureCallback> broadcaster =
+                new BroadcastDispatcher<CameraDeviceImpl.CaptureCallback>(
+                    replaceDeviceWithSession,
+                    localSink);
+
+        return new CallbackProxies.DeviceCaptureCallbackProxy(broadcaster);
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
index 4ee08ba..06c2c25 100644
--- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
@@ -33,7 +33,6 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.concurrent.Executor;
 
 import static com.android.internal.util.Preconditions.*;
 
@@ -60,14 +59,14 @@
      * (e.g. no pending captures, no repeating requests, no flush).</p>
      */
     CameraConstrainedHighSpeedCaptureSessionImpl(int id,
-            CameraCaptureSession.StateCallback callback, Executor stateExecutor,
+            CameraCaptureSession.StateCallback callback, Handler stateHandler,
             android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
             Handler deviceStateHandler, boolean configureSuccess,
             CameraCharacteristics characteristics) {
         mCharacteristics = characteristics;
         CameraCaptureSession.StateCallback wrapperCallback = new WrapperCallback(callback);
         mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, wrapperCallback,
-                stateExecutor, deviceImpl, deviceStateHandler, configureSuccess);
+                stateHandler, deviceImpl, deviceStateHandler, configureSuccess);
     }
 
     @Override
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index b328bb1..511fa43 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -35,10 +35,8 @@
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.camera2.utils.SubmitInfo;
 import android.hardware.camera2.utils.SurfaceUtils;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -60,7 +58,6 @@
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.Executor;
 
 /**
  * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
@@ -504,9 +501,8 @@
         for (Surface surface : outputs) {
             outConfigurations.add(new OutputConfiguration(surface));
         }
-        createCaptureSessionInternal(null, outConfigurations, callback,
-                checkAndWrapHandler(handler), /*operatingMode*/ICameraDeviceUser.NORMAL_MODE,
-                /*sessionParams*/ null);
+        createCaptureSessionInternal(null, outConfigurations, callback, handler,
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
     }
 
     @Override
@@ -521,7 +517,7 @@
         // OutputConfiguration objects are immutable, but need to have our own array
         List<OutputConfiguration> currentOutputs = new ArrayList<>(outputConfigurations);
 
-        createCaptureSessionInternal(null, currentOutputs, callback, checkAndWrapHandler(handler),
+        createCaptureSessionInternal(null, currentOutputs, callback, handler,
                 /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/null);
     }
 
@@ -541,9 +537,8 @@
         for (Surface surface : outputs) {
             outConfigurations.add(new OutputConfiguration(surface));
         }
-        createCaptureSessionInternal(inputConfig, outConfigurations, callback,
-                checkAndWrapHandler(handler), /*operatingMode*/ICameraDeviceUser.NORMAL_MODE,
-                /*sessionParams*/ null);
+        createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler,
+                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
     }
 
     @Override
@@ -571,8 +566,8 @@
             currentOutputs.add(new OutputConfiguration(output));
         }
         createCaptureSessionInternal(inputConfig, currentOutputs,
-                callback, checkAndWrapHandler(handler),
-                /*operatingMode*/ICameraDeviceUser.NORMAL_MODE, /*sessionParams*/ null);
+                callback, handler, /*operatingMode*/ICameraDeviceUser.NORMAL_MODE,
+                /*sessionParams*/ null);
     }
 
     @Override
@@ -587,8 +582,7 @@
         for (Surface surface : outputs) {
             outConfigurations.add(new OutputConfiguration(surface));
         }
-        createCaptureSessionInternal(null, outConfigurations, callback,
-                checkAndWrapHandler(handler),
+        createCaptureSessionInternal(null, outConfigurations, callback, handler,
                 /*operatingMode*/ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE,
                 /*sessionParams*/ null);
     }
@@ -603,8 +597,8 @@
         for (OutputConfiguration output : outputs) {
             currentOutputs.add(new OutputConfiguration(output));
         }
-        createCaptureSessionInternal(inputConfig, currentOutputs, callback,
-                checkAndWrapHandler(handler), operatingMode, /*sessionParams*/ null);
+        createCaptureSessionInternal(inputConfig, currentOutputs, callback, handler, operatingMode,
+                /*sessionParams*/ null);
     }
 
     @Override
@@ -618,17 +612,14 @@
         if (outputConfigs == null) {
             throw new IllegalArgumentException("Invalid output configurations");
         }
-        if (config.getExecutor() == null) {
-            throw new IllegalArgumentException("Invalid executor");
-        }
         createCaptureSessionInternal(config.getInputConfiguration(), outputConfigs,
-                config.getStateCallback(), config.getExecutor(), config.getSessionType(),
+                config.getStateCallback(), config.getHandler(), config.getSessionType(),
                 config.getSessionParameters());
     }
 
     private void createCaptureSessionInternal(InputConfiguration inputConfig,
             List<OutputConfiguration> outputConfigurations,
-            CameraCaptureSession.StateCallback callback, Executor executor,
+            CameraCaptureSession.StateCallback callback, Handler handler,
             int operatingMode, CaptureRequest sessionParams) throws CameraAccessException {
         synchronized(mInterfaceLock) {
             if (DEBUG) {
@@ -682,11 +673,12 @@
                 SurfaceUtils.checkConstrainedHighSpeedSurfaces(surfaces, /*fpsRange*/null, config);
 
                 newSession = new CameraConstrainedHighSpeedCaptureSessionImpl(mNextSessionId++,
-                        callback, executor, this, mDeviceHandler, configureSuccess,
+                        callback, handler, this, mDeviceHandler, configureSuccess,
                         mCharacteristics);
             } else {
                 newSession = new CameraCaptureSessionImpl(mNextSessionId++, input,
-                        callback, executor, this, mDeviceHandler, configureSuccess);
+                        callback, handler, this, mDeviceHandler,
+                        configureSuccess);
             }
 
             // TODO: wait until current session closes, then create the new session
@@ -971,12 +963,7 @@
                         }
                     }
                 };
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(resultDispatch);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                holder.getHandler().post(resultDispatch);
             } else {
                 Log.w(TAG, String.format(
                         "did not register callback to request %d",
@@ -997,9 +984,9 @@
     private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
             Handler handler, boolean repeating) throws CameraAccessException {
 
-        // Need a valid executor, or current thread needs to have a looper, if
+        // Need a valid handler, or current thread needs to have a looper, if
         // callback is valid
-        Executor executor = getExecutor(handler, callback);
+        handler = checkHandler(handler, callback);
 
         // Make sure that there all requests have at least 1 surface; all surfaces are non-null;
         // the surface isn't a physical stream surface for reprocessing request
@@ -1053,7 +1040,7 @@
             if (callback != null) {
                 mCaptureCallbackMap.put(requestInfo.getRequestId(),
                         new CaptureCallbackHolder(
-                            callback, requestList, executor, repeating, mNextSessionId - 1));
+                            callback, requestList, handler, repeating, mNextSessionId - 1));
             } else {
                 if (DEBUG) {
                     Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
@@ -1367,7 +1354,7 @@
         private final boolean mRepeating;
         private final CaptureCallback mCallback;
         private final List<CaptureRequest> mRequestList;
-        private final Executor mExecutor;
+        private final Handler mHandler;
         private final int mSessionId;
         /**
          * <p>Determine if the callback holder is for a constrained high speed request list that
@@ -1379,13 +1366,13 @@
         private final boolean mHasBatchedOutputs;
 
         CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
-                Executor executor, boolean repeating, int sessionId) {
-            if (callback == null || executor == null) {
+                Handler handler, boolean repeating, int sessionId) {
+            if (callback == null || handler == null) {
                 throw new UnsupportedOperationException(
                     "Must have a valid handler and a valid callback");
             }
             mRepeating = repeating;
-            mExecutor = executor;
+            mHandler = handler;
             mRequestList = new ArrayList<CaptureRequest>(requestList);
             mCallback = callback;
             mSessionId = sessionId;
@@ -1438,8 +1425,8 @@
             return getRequest(0);
         }
 
-        public Executor getExecutor() {
-            return mExecutor;
+        public Handler getHandler() {
+            return mHandler;
         }
 
         public int getSessionId() {
@@ -1823,12 +1810,7 @@
                         }
                     }
                 };
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(resultDispatch);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                holder.getHandler().post(resultDispatch);
             }
         }
     }
@@ -1879,7 +1861,7 @@
         private void scheduleNotifyError(int code) {
             mInError = true;
             CameraDeviceImpl.this.mDeviceHandler.post(obtainRunnable(
-                        CameraDeviceCallbacks::notifyError, this, code));
+                    CameraDeviceCallbacks::notifyError, this, code));
         }
 
         private void notifyError(int code) {
@@ -1947,41 +1929,36 @@
                 if (isClosed()) return;
 
                 // Dispatch capture start notice
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(
-                        new Runnable() {
-                            @Override
-                            public void run() {
-                                if (!CameraDeviceImpl.this.isClosed()) {
-                                    final int subsequenceId = resultExtras.getSubsequenceId();
-                                    final CaptureRequest request = holder.getRequest(subsequenceId);
+                holder.getHandler().post(
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            if (!CameraDeviceImpl.this.isClosed()) {
+                                final int subsequenceId = resultExtras.getSubsequenceId();
+                                final CaptureRequest request = holder.getRequest(subsequenceId);
 
-                                    if (holder.hasBatchedOutputs()) {
-                                        // Send derived onCaptureStarted for requests within the
-                                        // batch
-                                        final Range<Integer> fpsRange =
-                                            request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
-                                        for (int i = 0; i < holder.getRequestCount(); i++) {
-                                            holder.getCallback().onCaptureStarted(
-                                                CameraDeviceImpl.this,
-                                                holder.getRequest(i),
-                                                timestamp - (subsequenceId - i) *
-                                                NANO_PER_SECOND/fpsRange.getUpper(),
-                                                frameNumber - (subsequenceId - i));
-                                        }
-                                    } else {
+                                if (holder.hasBatchedOutputs()) {
+                                    // Send derived onCaptureStarted for requests within the batch
+                                    final Range<Integer> fpsRange =
+                                        request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+                                    for (int i = 0; i < holder.getRequestCount(); i++) {
                                         holder.getCallback().onCaptureStarted(
                                             CameraDeviceImpl.this,
-                                            holder.getRequest(resultExtras.getSubsequenceId()),
-                                            timestamp, frameNumber);
+                                            holder.getRequest(i),
+                                            timestamp - (subsequenceId - i) *
+                                            NANO_PER_SECOND/fpsRange.getUpper(),
+                                            frameNumber - (subsequenceId - i));
                                     }
+                                } else {
+                                    holder.getCallback().onCaptureStarted(
+                                        CameraDeviceImpl.this,
+                                        holder.getRequest(resultExtras.getSubsequenceId()),
+                                        timestamp, frameNumber);
                                 }
                             }
-                        });
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                        }
+                    });
+
             }
         }
 
@@ -2134,12 +2111,7 @@
                     finalResult = resultAsCapture;
                 }
 
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(resultDispatch);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                holder.getHandler().post(resultDispatch);
 
                 // Collect the partials for a total result; or mark the frame as totally completed
                 mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult,
@@ -2235,12 +2207,7 @@
                         }
                     };
                     // Dispatch the failure callback
-                    final long ident = Binder.clearCallingIdentity();
-                    try {
-                        holder.getExecutor().execute(failureDispatch);
-                    } finally {
-                        Binder.restoreCallingIdentity(ident);
-                    }
+                    holder.getHandler().post(failureDispatch);
                 }
             } else {
                 boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
@@ -2280,12 +2247,7 @@
                 checkAndFireSequenceComplete();
 
                 // Dispatch the failure callback
-                final long ident = Binder.clearCallingIdentity();
-                try {
-                    holder.getExecutor().execute(failureDispatch);
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+                holder.getHandler().post(failureDispatch);
             }
 
         }
@@ -2293,37 +2255,6 @@
     } // public class CameraDeviceCallbacks
 
     /**
-     * Instantiate a new Executor.
-     *
-     * <p>If the callback isn't null, check the handler and instantiate a new executor,
-     * otherwise instantiate a new executor in case handler is valid.</p>
-     */
-    static <T> Executor getExecutor(Handler handler, T callback) {
-        if (callback != null) {
-            return checkAndWrapHandler(handler);
-        }
-
-        if (handler != null) {
-            return new HandlerExecutor(handler);
-        }
-
-        return null;
-    }
-
-    /**
-     * Wrap Handler in Executor.
-     *
-     * <p>
-     * If handler is null, get the current thread's
-     * Looper to create a Executor with. If no looper exists, throw
-     * {@code IllegalArgumentException}.
-     * </p>
-     */
-    static Executor checkAndWrapHandler(Handler handler) {
-        return new HandlerExecutor(checkHandler(handler));
-    }
-
-    /**
      * Default handler management.
      *
      * <p>
diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java
index 7bdb4a2..a79a6c1 100644
--- a/core/java/android/hardware/camera2/params/SessionConfiguration.java
+++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java
@@ -17,10 +17,10 @@
 
 package android.hardware.camera2.params;
 
-import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.IntDef;
+import android.os.Handler;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
@@ -31,7 +31,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.concurrent.Executor;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -79,7 +78,7 @@
     private List<OutputConfiguration> mOutputConfigurations;
     private CameraCaptureSession.StateCallback mStateCallback;
     private int mSessionType;
-    private Executor mExecutor = null;
+    private Handler mHandler = null;
     private InputConfiguration mInputConfig = null;
     private CaptureRequest mSessionParameters = null;
 
@@ -88,9 +87,10 @@
      *
      * @param sessionType The session type.
      * @param outputs A list of output configurations for the capture session.
-     * @param executor The executor which should be used to invoke the callback. In general it is
-     *                 recommended that camera operations are not done on the main (UI) thread.
      * @param cb A state callback interface implementation.
+     * @param handler The handler on which the callback will be invoked. If it is
+     *                set to null, the callback will be invoked on the current thread's
+     *                {@link android.os.Looper looper}.
      *
      * @see #SESSION_REGULAR
      * @see #SESSION_HIGH_SPEED
@@ -101,12 +101,11 @@
      */
     public SessionConfiguration(@SessionMode int sessionType,
             @NonNull List<OutputConfiguration> outputs,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull CameraCaptureSession.StateCallback cb) {
+            @NonNull CameraCaptureSession.StateCallback cb, @Nullable Handler handler) {
         mSessionType = sessionType;
         mOutputConfigurations = Collections.unmodifiableList(new ArrayList<>(outputs));
         mStateCallback = cb;
-        mExecutor = executor;
+        mHandler = handler;
     }
 
     /**
@@ -137,12 +136,14 @@
     }
 
     /**
-     * Retrieve the {@link java.util.concurrent.Executor} for the capture session.
+     * Retrieve the {@link CameraCaptureSession.StateCallback} for the capture session.
      *
-     * @return The Executor on which the callback will be invoked.
+     * @return The handler on which the callback will be invoked. If it is
+     *         set to null, the callback will be invoked on the current thread's
+     *         {@link android.os.Looper looper}.
      */
-    public Executor getExecutor() {
-        return mExecutor;
+    public Handler getHandler() {
+        return mHandler;
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/utils/TaskDrainer.java b/core/java/android/hardware/camera2/utils/TaskDrainer.java
index e71f26a..ed30ff3 100644
--- a/core/java/android/hardware/camera2/utils/TaskDrainer.java
+++ b/core/java/android/hardware/camera2/utils/TaskDrainer.java
@@ -15,11 +15,11 @@
  */
 package android.hardware.camera2.utils;
 
+import android.os.Handler;
 import android.util.Log;
 
 import java.util.HashSet;
 import java.util.Set;
-import java.util.concurrent.Executor;
 
 import static com.android.internal.util.Preconditions.*;
 
@@ -55,7 +55,7 @@
     private static final String TAG = "TaskDrainer";
     private final boolean DEBUG = false;
 
-    private final Executor mExecutor;
+    private final Handler mHandler;
     private final DrainListener mListener;
     private final String mName;
 
@@ -73,27 +73,28 @@
 
     /**
      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
-     * via the {@code executor}.
+     * via the {@code handler}.
      *
-     * @param executor a non-{@code null} executor to use for listener execution
+     * @param handler a non-{@code null} handler to use to post runnables to
      * @param listener a non-{@code null} listener where {@code onDrained} will be called
      */
-    public TaskDrainer(Executor executor, DrainListener listener) {
-        mExecutor = checkNotNull(executor, "executor must not be null");
+    public TaskDrainer(Handler handler, DrainListener listener) {
+        mHandler = checkNotNull(handler, "handler must not be null");
         mListener = checkNotNull(listener, "listener must not be null");
         mName = null;
     }
 
     /**
      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
-     * via the {@code executor}.
+     * via the {@code handler}.
      *
-     * @param executor a non-{@code null} executor to use for listener execution
+     * @param handler a non-{@code null} handler to use to post runnables to
      * @param listener a non-{@code null} listener where {@code onDrained} will be called
      * @param name an optional name used for debug logging
      */
-    public TaskDrainer(Executor executor, DrainListener listener, String name) {
-        mExecutor = checkNotNull(executor, "executor must not be null");
+    public TaskDrainer(Handler handler, DrainListener listener, String name) {
+        // XX: Probably don't need a handler at all here
+        mHandler = checkNotNull(handler, "handler must not be null");
         mListener = checkNotNull(listener, "listener must not be null");
         mName = name;
     }
@@ -199,12 +200,15 @@
     }
 
     private void postDrained() {
-        mExecutor.execute(() -> {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
                 if (DEBUG) {
                     Log.v(TAG + "[" + mName + "]", "onDrained");
                 }
 
                 mListener.onDrained();
+            }
         });
     }
 }
diff --git a/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java
index 9615450..f6272c9 100644
--- a/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java
+++ b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java
@@ -16,8 +16,7 @@
 package android.hardware.camera2.utils;
 
 import android.hardware.camera2.utils.TaskDrainer.DrainListener;
-
-import java.util.concurrent.Executor;
+import android.os.Handler;
 
 /**
  * Keep track of a single concurrent task starting and finishing;
@@ -39,25 +38,25 @@
 
     /**
      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
-     * via the {@code executor}.
+     * via the {@code handler}.
      *
-     * @param executor a non-{@code null} executor to use for listener execution
+     * @param handler a non-{@code null} handler to use to post runnables to
      * @param listener a non-{@code null} listener where {@code onDrained} will be called
      */
-    public TaskSingleDrainer(Executor executor, DrainListener listener) {
-        mTaskDrainer = new TaskDrainer<>(executor, listener);
+    public TaskSingleDrainer(Handler handler, DrainListener listener) {
+        mTaskDrainer = new TaskDrainer<>(handler, listener);
     }
 
     /**
      * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
-     * via the {@code executor}.
+     * via the {@code handler}.
      *
-     * @param executor a non-{@code null} executor to use for listener execution
+     * @param handler a non-{@code null} handler to use to post runnables to
      * @param listener a non-{@code null} listener where {@code onDrained} will be called
      * @param name an optional name used for debug logging
      */
-    public TaskSingleDrainer(Executor executor, DrainListener listener, String name) {
-        mTaskDrainer = new TaskDrainer<>(executor, listener, name);
+    public TaskSingleDrainer(Handler handler, DrainListener listener, String name) {
+        mTaskDrainer = new TaskDrainer<>(handler, listener, name);
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index f468942..504f840 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -23,6 +23,7 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.SurfaceControl;
 
 /**
  * Display manager local system service interface.
@@ -115,7 +116,7 @@
      * Called by the window manager to perform traversals while holding a
      * surface flinger transaction.
      */
-    public abstract void performTraversalInTransactionFromWindowManager();
+    public abstract void performTraversal(SurfaceControl.Transaction t);
 
     /**
      * Tells the display manager about properties of the display that depend on the windows on it.
diff --git a/core/java/android/net/INetdEventCallback.aidl b/core/java/android/net/INetdEventCallback.aidl
index 1fd9423..1e75bf4 100644
--- a/core/java/android/net/INetdEventCallback.aidl
+++ b/core/java/android/net/INetdEventCallback.aidl
@@ -20,8 +20,9 @@
 oneway interface INetdEventCallback {
 
     // Possible addNetdEventCallback callers.
-    const int CALLBACK_CALLER_DEVICE_POLICY = 0;
-    const int CALLBACK_CALLER_NETWORK_WATCHLIST = 1;
+    const int CALLBACK_CALLER_CONNECTIVITY_SERVICE = 0;
+    const int CALLBACK_CALLER_DEVICE_POLICY = 1;
+    const int CALLBACK_CALLER_NETWORK_WATCHLIST = 2;
 
     /**
      * Reports a single DNS lookup function call.
@@ -39,6 +40,18 @@
             int uid);
 
     /**
+     * Represents a private DNS validation success or failure.
+     * This method must not block or perform long-running operations.
+     *
+     * @param netId the ID of the network the validation was performed on.
+     * @param ipAddress the IP address for which validation was performed.
+     * @param hostname the hostname for which validation was performed.
+     * @param validated whether or not validation was successful.
+     */
+    void onPrivateDnsValidationEvent(int netId, String ipAddress, String hostname,
+            boolean validated);
+
+    /**
      * Reports a single connect library call.
      * This method must not block or perform long-running operations.
      *
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 29b7931..60f7295 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3727,7 +3727,7 @@
         public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
-         * Whether the haptic feedback (long presses, ...) are enabled. The value is
+         * Whether haptic feedback (Vibrate on tap) is enabled. The value is
          * boolean (1 or 0).
          */
         public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
@@ -10271,31 +10271,6 @@
                 "battery_saver_device_specific_constants";
 
         /**
-         * Battery anomaly detection specific settings
-         * This is encoded as a key=value list, separated by commas.
-         * wakeup_blacklisted_tags is a string, encoded as a set of tags, encoded via
-         * {@link Uri#encode(String)}, separated by colons. Ex:
-         *
-         * "anomaly_detection_enabled=true,wakelock_threshold=2000,wakeup_alarm_enabled=true,"
-         * "wakeup_alarm_threshold=10,wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon"
-         *
-         * The following keys are supported:
-         *
-         * <pre>
-         * anomaly_detection_enabled       (boolean)
-         * wakelock_enabled                (boolean)
-         * wakelock_threshold              (long)
-         * wakeup_alarm_enabled            (boolean)
-         * wakeup_alarm_threshold          (long)
-         * wakeup_blacklisted_tags         (string)
-         * bluetooth_scan_enabled          (boolean)
-         * bluetooth_scan_threshold        (long)
-         * </pre>
-         * @hide
-         */
-        public static final String ANOMALY_DETECTION_CONSTANTS = "anomaly_detection_constants";
-
-        /**
          * Battery tip specific settings
          * This is encoded as a key=value list, separated by commas. Ex:
          *
@@ -10324,6 +10299,31 @@
         public static final String BATTERY_TIP_CONSTANTS = "battery_tip_constants";
 
         /**
+         * Battery anomaly detection specific settings
+         * This is encoded as a key=value list, separated by commas.
+         * wakeup_blacklisted_tags is a string, encoded as a set of tags, encoded via
+         * {@link Uri#encode(String)}, separated by colons. Ex:
+         *
+         * "anomaly_detection_enabled=true,wakelock_threshold=2000,wakeup_alarm_enabled=true,"
+         * "wakeup_alarm_threshold=10,wakeup_blacklisted_tags=tag1:tag2:with%2Ccomma:with%3Acolon"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * anomaly_detection_enabled       (boolean)
+         * wakelock_enabled                (boolean)
+         * wakelock_threshold              (long)
+         * wakeup_alarm_enabled            (boolean)
+         * wakeup_alarm_threshold          (long)
+         * wakeup_blacklisted_tags         (string)
+         * bluetooth_scan_enabled          (boolean)
+         * bluetooth_scan_threshold        (long)
+         * </pre>
+         * @hide
+         */
+        public static final String ANOMALY_DETECTION_CONSTANTS = "anomaly_detection_constants";
+
+        /**
          * An integer to show the version of the anomaly config. Ex: 1, which means
          * current version is 1.
          * @hide
@@ -10598,7 +10598,7 @@
          * Default: 1
          * @hide
          */
-        public static final java.lang.String APP_STANDBY_ENABLED = "app_standby_enabled";
+        public static final String APP_STANDBY_ENABLED = "app_standby_enabled";
 
         /**
          * Whether or not app auto restriction is enabled. When it is enabled, settings app will
@@ -10609,7 +10609,7 @@
          *
          * @hide
          */
-        public static final java.lang.String APP_AUTO_RESTRICTION_ENABLED =
+        public static final String APP_AUTO_RESTRICTION_ENABLED =
                 "app_auto_restriction_enabled";
 
         private static final Validator APP_AUTO_RESTRICTION_ENABLED_VALIDATOR =
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index 19a018e..3d8b74b 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -301,12 +301,6 @@
      *         provide a new logical channel.
      */
     public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
-
-        if ((mReader.getName().startsWith("SIM")) && (aid == null)) {
-            Log.e(TAG, "NULL AID not supported on " + mReader.getName());
-            return null;
-        }
-
         if (!mService.isConnected()) {
             throw new IllegalStateException("service not connected to system");
         }
diff --git a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
index 4580c47..00f54e1 100644
--- a/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
+++ b/core/java/android/security/keystore/recovery/KeyChainSnapshot.java
@@ -18,12 +18,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.os.BadParcelableException;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.util.Preconditions;
 
 import java.security.cert.CertPath;
+import java.security.cert.CertificateException;
 import java.util.List;
 
 /**
@@ -54,7 +56,7 @@
     private long mCounterId = DEFAULT_COUNTER_ID;
     private byte[] mServerParams;
     private byte[] mPublicKey;  // The raw public key bytes used
-    private CertPath mCertPath;  // The certificate path including the intermediate certificates
+    private RecoveryCertPath mCertPath;  // The cert path including necessary intermediate certs
     private List<KeyChainProtectionParams> mKeyChainProtectionParams;
     private List<WrappedApplicationKey> mEntryRecoveryData;
     private byte[] mEncryptedRecoveryKeyBlob;
@@ -127,7 +129,17 @@
      */
     // TODO: Change to @NonNull
     public CertPath getTrustedHardwareCertPath() {
-        return mCertPath;
+        if (mCertPath == null) {
+            return null;
+        } else {
+            try {
+                return mCertPath.getCertPath();
+            } catch (CertificateException e) {
+                // Rethrow an unchecked exception as it should not happen. If such an issue exists,
+                // an exception should have been thrown during service initialization.
+                throw new BadParcelableException(e);
+            }
+        }
     }
 
     /**
@@ -232,11 +244,17 @@
          * contain a certificate of the trusted hardware public key and any necessary intermediate
          * certificates.
          *
-         * @param certPath The public key
+         * @param certPath The certificate path
+         * @throws CertificateException if the given certificate path cannot be encoded properly
          * @return This builder.
          */
-        public Builder setTrustedHardwareCertPath(CertPath certPath) {
-            mInstance.mCertPath = certPath;
+        public Builder setTrustedHardwareCertPath(CertPath certPath) throws CertificateException {
+            // TODO: Make it NonNull when the caller code is all updated
+            if (certPath == null) {
+                mInstance.mCertPath = null;
+            } else {
+                mInstance.mCertPath = RecoveryCertPath.createRecoveryCertPath(certPath);
+            }
             return this;
         }
 
@@ -302,6 +320,7 @@
         out.writeLong(mCounterId);
         out.writeByteArray(mServerParams);
         out.writeByteArray(mPublicKey);
+        out.writeTypedObject(mCertPath, /* no flags */ 0);
     }
 
     /**
@@ -316,6 +335,7 @@
         mCounterId = in.readLong();
         mServerParams = in.createByteArray();
         mPublicKey = in.createByteArray();
+        mCertPath = in.readTypedObject(RecoveryCertPath.CREATOR);
     }
 
     @Override
diff --git a/core/java/android/util/KeyValueSettingObserver.java b/core/java/android/util/KeyValueSettingObserver.java
new file mode 100644
index 0000000..9fca8b2
--- /dev/null
+++ b/core/java/android/util/KeyValueSettingObserver.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+
+/**
+ * Abstract class for observing changes to a specified setting stored as a comma-separated key value
+ * list of parameters. Registers and unregisters a {@link ContentObserver} and handles updates when
+ * the setting changes.
+ *
+ * <p>Subclasses should pass in the relevant setting's {@link Uri} in the constructor and implement
+ * {@link #update(KeyValueListParser)} to receive updates when the value changes.
+ * Calls to {@link #update(KeyValueListParser)} only trigger after calling {@link
+ * #start()}.
+ *
+ * <p>To get the most up-to-date parameter values, first call {@link #start()} before accessing the
+ * values to start observing changes, and then call {@link #stop()} once finished.
+ *
+ * @hide
+ */
+public abstract class KeyValueSettingObserver {
+    private static final String TAG = "KeyValueSettingObserver";
+
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+    private final ContentObserver mObserver;
+    private final ContentResolver mResolver;
+    private final Uri mSettingUri;
+
+    public KeyValueSettingObserver(Handler handler, ContentResolver resolver,
+            Uri uri) {
+        mObserver = new SettingObserver(handler);
+        mResolver = resolver;
+        mSettingUri = uri;
+    }
+
+    /** Starts observing changes for the setting. Pair with {@link #stop()}. */
+    public void start() {
+        mResolver.registerContentObserver(mSettingUri, false, mObserver);
+        setParserValue();
+        update(mParser);
+    }
+
+    /** Stops observing changes for the setting. */
+    public void stop() {
+        mResolver.unregisterContentObserver(mObserver);
+    }
+
+    /**
+     * Returns the {@link String} representation of the setting. Subclasses should implement this
+     * for their setting.
+     */
+    public abstract String getSettingValue(ContentResolver resolver);
+
+    /** Updates the parser with the current setting value. */
+    private void setParserValue() {
+        String setting = getSettingValue(mResolver);
+        try {
+            mParser.setString(setting);
+        } catch (IllegalArgumentException e) {
+            Slog.e(TAG, "Malformed setting: " + setting);
+        }
+    }
+
+    /** Subclasses should implement this to update references to their parameters. */
+    public abstract void update(KeyValueListParser parser);
+
+    private class SettingObserver extends ContentObserver {
+        private SettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            setParserValue();
+            update(mParser);
+        }
+    }
+}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 5607b11..89684ca 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -51,4 +51,12 @@
      * and then enable it mid-animation to start receiving touch events.
      */
     void setInputConsumerEnabled(boolean enabled);
+
+    /**
+    * Informs the system whether the animation targets passed into
+    * IRecentsAnimationRunner.onAnimationStart are currently behind the system bars. If they are,
+    * they can control the SystemUI flags, otherwise the SystemUI flags from home activity will be
+    * taken.
+    */
+    void setAnimationTargetsBehindSystemBars(boolean behindSystemBars);
 }
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index 8def435..d2240e1 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -16,10 +16,14 @@
 
 package android.view;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
 import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.ActivityType;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.SparseArray;
 import android.view.WindowManager.TransitionType;
 
@@ -30,7 +34,7 @@
  */
 public class RemoteAnimationDefinition implements Parcelable {
 
-    private final SparseArray<RemoteAnimationAdapter> mTransitionAnimationMap;
+    private final SparseArray<RemoteAnimationAdapterEntry> mTransitionAnimationMap;
 
     public RemoteAnimationDefinition() {
         mTransitionAnimationMap = new SparseArray<>();
@@ -40,34 +44,70 @@
      * Registers a remote animation for a specific transition.
      *
      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param activityTypeFilter The remote animation only runs if an activity with type of this
+     *                           parameter is involved in the transition.
+     * @param adapter The adapter that described how to run the remote animation.
+     */
+    public void addRemoteAnimation(@TransitionType int transition,
+            @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) {
+        mTransitionAnimationMap.put(transition,
+                new RemoteAnimationAdapterEntry(adapter, activityTypeFilter));
+    }
+
+    /**
+     * Registers a remote animation for a specific transition without defining an activity type
+     * filter.
+     *
+     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
      * @param adapter The adapter that described how to run the remote animation.
      */
     public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
-        mTransitionAnimationMap.put(transition, adapter);
+        addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter);
     }
 
     /**
      * Checks whether a remote animation for specific transition is defined.
      *
      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param activityTypes The set of activity types of activities that are involved in the
+     *                      transition. Will be used for filtering.
      * @return Whether this definition has defined a remote animation for the specified transition.
      */
-    public boolean hasTransition(@TransitionType int transition) {
-        return mTransitionAnimationMap.get(transition) != null;
+    public boolean hasTransition(@TransitionType int transition, ArraySet<Integer> activityTypes) {
+        return getAdapter(transition, activityTypes) != null;
     }
 
     /**
      * Retrieves the remote animation for a specific transition.
      *
      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param activityTypes The set of activity types of activities that are involved in the
+     *                      transition. Will be used for filtering.
      * @return The remote animation adapter for the specified transition.
      */
-    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition) {
-        return mTransitionAnimationMap.get(transition);
+    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition,
+            ArraySet<Integer> activityTypes) {
+        final RemoteAnimationAdapterEntry entry = mTransitionAnimationMap.get(transition);
+        if (entry == null) {
+            return null;
+        }
+        if (entry.activityTypeFilter == ACTIVITY_TYPE_UNDEFINED
+                || activityTypes.contains(entry.activityTypeFilter)) {
+            return entry.adapter;
+        } else {
+            return null;
+        }
     }
 
     public RemoteAnimationDefinition(Parcel in) {
-        mTransitionAnimationMap = in.readSparseArray(null /* loader */);
+        final int size = in.readInt();
+        mTransitionAnimationMap = new SparseArray<>(size);
+        for (int i = 0; i < size; i++) {
+            final int transition = in.readInt();
+            final RemoteAnimationAdapterEntry entry = in.readTypedObject(
+                    RemoteAnimationAdapterEntry.CREATOR);
+            mTransitionAnimationMap.put(transition, entry);
+        }
     }
 
     /**
@@ -76,7 +116,7 @@
      */
     public void setCallingPid(int pid) {
         for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
-            mTransitionAnimationMap.valueAt(i).setCallingPid(pid);
+            mTransitionAnimationMap.valueAt(i).adapter.setCallingPid(pid);
         }
     }
 
@@ -87,7 +127,12 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeSparseArray((SparseArray) mTransitionAnimationMap);
+        final int size = mTransitionAnimationMap.size();
+        dest.writeInt(size);
+        for (int i = 0; i < size; i++) {
+            dest.writeInt(mTransitionAnimationMap.keyAt(i));
+            dest.writeTypedObject(mTransitionAnimationMap.valueAt(i), flags);
+        }
     }
 
     public static final Creator<RemoteAnimationDefinition> CREATOR =
@@ -100,4 +145,50 @@
             return new RemoteAnimationDefinition[size];
         }
     };
+
+    private static class RemoteAnimationAdapterEntry implements Parcelable {
+
+        final RemoteAnimationAdapter adapter;
+
+        /**
+         * Only run the transition if one of the activities matches the filter.
+         * {@link WindowConfiguration.ACTIVITY_TYPE_UNDEFINED} means no filter
+         */
+        @ActivityType final int activityTypeFilter;
+
+        RemoteAnimationAdapterEntry(RemoteAnimationAdapter adapter, int activityTypeFilter) {
+            this.adapter = adapter;
+            this.activityTypeFilter = activityTypeFilter;
+        }
+
+        private RemoteAnimationAdapterEntry(Parcel in) {
+            adapter = in.readParcelable(RemoteAnimationAdapter.class.getClassLoader());
+            activityTypeFilter = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeParcelable(adapter, flags);
+            dest.writeInt(activityTypeFilter);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private static final Creator<RemoteAnimationAdapterEntry> CREATOR
+                = new Creator<RemoteAnimationAdapterEntry>() {
+
+            @Override
+            public RemoteAnimationAdapterEntry createFromParcel(Parcel in) {
+                return new RemoteAnimationAdapterEntry(in);
+            }
+
+            @Override
+            public RemoteAnimationAdapterEntry[] newArray(int size) {
+                return new RemoteAnimationAdapterEntry[size];
+            }
+        };
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf0e2eb..b624870 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6546,7 +6546,7 @@
             } finally {
                 // Set it to already called so it's not called twice when called by
                 // performClickInternal()
-                mPrivateFlags |= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+                mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
             }
         }
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f39b73e..5178a97 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -251,7 +251,7 @@
  * density, or high density screens, respectively. For example:
  * <pre>
  * &lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" /&gt;</pre>
- * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ration of 1.5,
+ * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ratio of 1.5,
  * which is the high density pixel ratio.
  * </li>
  * </ul>
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index 07593a5..49e11b8 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -19,6 +19,7 @@
 import android.app.LoadedApk;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.ChildZygoteProcess;
 import android.os.Process;
@@ -93,11 +94,17 @@
         synchronized (sLock) {
             sMultiprocessEnabled = enabled;
 
-            // When multi-process is disabled, kill the zygote. When it is enabled,
-            // the zygote is not explicitly started here to avoid waiting on the
-            // zygote launch at boot. Instead, the zygote will be started when it is
-            // first needed in getProcess().
-            if (!enabled) {
+            // When toggling between multi-process being on/off, start or stop the
+            // zygote. If it is enabled and the zygote is not yet started, launch it.
+            // Otherwise, kill it. The name may be null if the package information has
+            // not yet been resolved.
+            if (enabled) {
+                // Run on a background thread as this waits for the zygote to start and we don't
+                // want to block the caller on this. It's okay if this is delayed as anyone trying
+                // to use the zygote will call it first anyway.
+                AsyncTask.THREAD_POOL_EXECUTOR.execute(WebViewZygote::getProcess);
+            } else {
+                // No need to run this in the background, it's very brief.
                 stopZygoteLocked();
             }
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6fe64a0..f77a6b7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -291,6 +291,7 @@
  * @attr ref android.R.styleable#TextView_drawableTintMode
  * @attr ref android.R.styleable#TextView_lineSpacingExtra
  * @attr ref android.R.styleable#TextView_lineSpacingMultiplier
+ * @attr ref android.R.styleable#TextView_justificationMode
  * @attr ref android.R.styleable#TextView_marqueeRepeatLimit
  * @attr ref android.R.styleable#TextView_inputType
  * @attr ref android.R.styleable#TextView_imeOptions
diff --git a/core/java/com/android/internal/backup/LocalTransportParameters.java b/core/java/com/android/internal/backup/LocalTransportParameters.java
index 390fae9..154e79d 100644
--- a/core/java/com/android/internal/backup/LocalTransportParameters.java
+++ b/core/java/com/android/internal/backup/LocalTransportParameters.java
@@ -16,62 +16,32 @@
 
 package com.android.internal.backup;
 
+import android.util.KeyValueSettingObserver;
 import android.content.ContentResolver;
-import android.database.ContentObserver;
 import android.os.Handler;
 import android.provider.Settings;
 import android.util.KeyValueListParser;
-import android.util.Slog;
 
-class LocalTransportParameters {
+class LocalTransportParameters extends KeyValueSettingObserver {
     private static final String TAG = "LocalTransportParams";
     private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
     private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
 
-    private final KeyValueListParser mParser = new KeyValueListParser(',');
-    private final ContentObserver mObserver;
-    private final ContentResolver mResolver;
     private boolean mFakeEncryptionFlag;
 
     LocalTransportParameters(Handler handler, ContentResolver resolver) {
-        mObserver = new Observer(handler);
-        mResolver = resolver;
-    }
-
-    /** Observes for changes in the setting. This method MUST be paired with {@link #stop()}. */
-    void start() {
-        mResolver.registerContentObserver(Settings.Secure.getUriFor(SETTING), false, mObserver);
-        update();
-    }
-
-    /** Stop observing for changes in the setting. */
-    void stop() {
-        mResolver.unregisterContentObserver(mObserver);
+        super(handler, resolver, Settings.Secure.getUriFor(SETTING));
     }
 
     boolean isFakeEncryptionFlag() {
         return mFakeEncryptionFlag;
     }
 
-    private void update() {
-        String parameters = "";
-        try {
-            parameters = Settings.Secure.getString(mResolver, SETTING);
-        } catch (IllegalArgumentException e) {
-            Slog.e(TAG, "Malformed " + SETTING + " setting: " + e.getMessage());
-        }
-        mParser.setString(parameters);
-        mFakeEncryptionFlag = mParser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
+    public String getSettingValue(ContentResolver resolver) {
+        return Settings.Secure.getString(resolver, SETTING);
     }
 
-    private class Observer extends ContentObserver {
-        private Observer(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            update();
-        }
+    public void update(KeyValueListParser parser) {
+        mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
     }
 }
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 44adbb2..5950436 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -50,6 +50,7 @@
     public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
     public static String HEAVY_WEIGHT_APP = "HEAVY_WEIGHT_APP";
     public static String SYSTEM_CHANGES = "SYSTEM_CHANGES";
+    public static String DO_NOT_DISTURB = "DO_NOT_DISTURB";
 
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -158,6 +159,11 @@
                 NotificationManager.IMPORTANCE_LOW);
         channelsList.add(systemChanges);
 
+        NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB,
+                context.getString(R.string.notification_channel_do_not_disturb),
+                NotificationManager.IMPORTANCE_LOW);
+        channelsList.add(dndChanges);
+
         nm.createNotificationChannels(channelsList);
     }
 
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 9d012de..0c5ea63 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
@@ -33,6 +34,7 @@
 import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.widget.LinearLayout;
 
@@ -108,13 +110,6 @@
     private CharSequence mContentDescription;
     private CharSequence mTooltipText;
 
-    private static String sLanguage;
-    private static String sPrependShortcutLabel;
-    private static String sEnterShortcutLabel;
-    private static String sDeleteShortcutLabel;
-    private static String sSpaceShortcutLabel;
-
-
     /**
      * Instantiates this menu item.
      *
@@ -130,20 +125,6 @@
     MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
             CharSequence title, int showAsAction) {
 
-        String lang = menu.getContext().getResources().getConfiguration().locale.toString();
-        if (sPrependShortcutLabel == null || !lang.equals(sLanguage)) {
-            sLanguage = lang;
-            // This is instantiated from the UI thread, so no chance of sync issues
-            sPrependShortcutLabel = menu.getContext().getResources().getString(
-                    com.android.internal.R.string.prepend_shortcut_label);
-            sEnterShortcutLabel = menu.getContext().getResources().getString(
-                    com.android.internal.R.string.menu_enter_shortcut_label);
-            sDeleteShortcutLabel = menu.getContext().getResources().getString(
-                    com.android.internal.R.string.menu_delete_shortcut_label);
-            sSpaceShortcutLabel = menu.getContext().getResources().getString(
-                    com.android.internal.R.string.menu_space_shortcut_label);
-        }
-
         mMenu = menu;
         mId = id;
         mGroup = group;
@@ -353,19 +334,45 @@
             return "";
         }
 
-        StringBuilder sb = new StringBuilder(sPrependShortcutLabel);
+        final Resources res = mMenu.getContext().getResources();
+
+        StringBuilder sb = new StringBuilder();
+        if (ViewConfiguration.get(mMenu.getContext()).hasPermanentMenuKey()) {
+            // Only prepend "Menu+" if there is a hardware menu key.
+            sb.append(res.getString(
+                com.android.internal.R.string.prepend_shortcut_label));
+        }
+
+        final int modifiers =
+            mMenu.isQwertyMode() ? mShortcutAlphabeticModifiers : mShortcutNumericModifiers;
+        appendModifier(sb, modifiers, KeyEvent.META_META_ON, res.getString(
+            com.android.internal.R.string.menu_meta_shortcut_label));
+        appendModifier(sb, modifiers, KeyEvent.META_CTRL_ON, res.getString(
+            com.android.internal.R.string.menu_ctrl_shortcut_label));
+        appendModifier(sb, modifiers, KeyEvent.META_ALT_ON, res.getString(
+            com.android.internal.R.string.menu_alt_shortcut_label));
+        appendModifier(sb, modifiers, KeyEvent.META_SHIFT_ON, res.getString(
+            com.android.internal.R.string.menu_shift_shortcut_label));
+        appendModifier(sb, modifiers, KeyEvent.META_SYM_ON, res.getString(
+            com.android.internal.R.string.menu_sym_shortcut_label));
+        appendModifier(sb, modifiers, KeyEvent.META_FUNCTION_ON, res.getString(
+            com.android.internal.R.string.menu_function_shortcut_label));
+
         switch (shortcut) {
 
             case '\n':
-                sb.append(sEnterShortcutLabel);
+                sb.append(res.getString(
+                    com.android.internal.R.string.menu_enter_shortcut_label));
                 break;
 
             case '\b':
-                sb.append(sDeleteShortcutLabel);
+                sb.append(res.getString(
+                    com.android.internal.R.string.menu_delete_shortcut_label));
                 break;
 
             case ' ':
-                sb.append(sSpaceShortcutLabel);
+                sb.append(res.getString(
+                    com.android.internal.R.string.menu_space_shortcut_label));
                 break;
 
             default:
@@ -376,6 +383,12 @@
         return sb.toString();
     }
 
+    private static void appendModifier(StringBuilder sb, int mask, int modifier, String label) {
+        if ((mask & modifier) == modifier) {
+            sb.append(label);
+        }
+    }
+
     /**
      * @return Whether this menu item should be showing shortcuts (depends on
      *         whether the menu should show shortcuts and whether this item has
diff --git a/core/java/com/android/server/net/BaseNetdEventCallback.java b/core/java/com/android/server/net/BaseNetdEventCallback.java
index 3d3a3d0..fdba2f3 100644
--- a/core/java/com/android/server/net/BaseNetdEventCallback.java
+++ b/core/java/com/android/server/net/BaseNetdEventCallback.java
@@ -32,6 +32,12 @@
     }
 
     @Override
+    public void onPrivateDnsValidationEvent(int netId, String ipAddress,
+            String hostname, boolean validated) {
+        // default no-op
+    }
+
+    @Override
     public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) {
         // default no-op
     }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d05be2c..7c8a52d 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -71,6 +71,9 @@
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 
+#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
+                              append(StringPrintf(__VA_ARGS__))
+
 static pid_t gSystemServerPid = 0;
 
 static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
@@ -186,30 +189,32 @@
 
 // Calls POSIX setgroups() using the int[] object as an argument.
 // A NULL argument is tolerated.
-static void SetGids(JNIEnv* env, jintArray javaGids) {
+static bool SetGids(JNIEnv* env, jintArray javaGids, std::string* error_msg) {
   if (javaGids == NULL) {
-    return;
+    return true;
   }
 
   ScopedIntArrayRO gids(env, javaGids);
   if (gids.get() == NULL) {
-    RuntimeAbort(env, __LINE__, "Getting gids int array failed");
+    *error_msg = CREATE_ERROR("Getting gids int array failed");
+    return false;
   }
   int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
   if (rc == -1) {
-    std::ostringstream oss;
-    oss << "setgroups failed: " << strerror(errno) << ", gids.size=" << gids.size();
-    RuntimeAbort(env, __LINE__, oss.str().c_str());
+    *error_msg = CREATE_ERROR("setgroups failed: %s, gids.size=%zu", strerror(errno), gids.size());
+    return false;
   }
+
+  return true;
 }
 
 // Sets the resource limits via setrlimit(2) for the values in the
 // two-dimensional array of integers that's passed in. The second dimension
 // contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
 // treated as an empty array.
-static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+static bool SetRLimits(JNIEnv* env, jobjectArray javaRlimits, std::string* error_msg) {
   if (javaRlimits == NULL) {
-    return;
+    return true;
   }
 
   rlimit rlim;
@@ -219,7 +224,8 @@
     ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
     ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
     if (javaRlimit.size() != 3) {
-      RuntimeAbort(env, __LINE__, "rlimits array must have a second dimension of size 3");
+      *error_msg = CREATE_ERROR("rlimits array must have a second dimension of size 3");
+      return false;
     }
 
     rlim.rlim_cur = javaRlimit[1];
@@ -227,11 +233,13 @@
 
     int rc = setrlimit(javaRlimit[0], &rlim);
     if (rc == -1) {
-      ALOGE("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
+      *error_msg = CREATE_ERROR("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
             rlim.rlim_max);
-      RuntimeAbort(env, __LINE__, "setrlimit failed");
+      return false;
     }
   }
+
+  return true;
 }
 
 // The debug malloc library needs to know whether it's the zygote or a child.
@@ -259,14 +267,16 @@
   }
 }
 
-static void EnableKeepCapabilities(JNIEnv* env) {
+static bool EnableKeepCapabilities(std::string* error_msg) {
   int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
   if (rc == -1) {
-    RuntimeAbort(env, __LINE__, "prctl(PR_SET_KEEPCAPS) failed");
+    *error_msg = CREATE_ERROR("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno));
+    return false;
   }
+  return true;
 }
 
-static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+static bool DropCapabilitiesBoundingSet(std::string* error_msg) {
   for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
     int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
     if (rc == -1) {
@@ -274,14 +284,15 @@
         ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
               "your kernel is compiled with file capabilities support");
       } else {
-        ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
-        RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed");
+        *error_msg = CREATE_ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
+        return false;
       }
     }
   }
+  return true;
 }
 
-static void SetInheritable(JNIEnv* env, uint64_t inheritable) {
+static bool SetInheritable(uint64_t inheritable, std::string* error_msg) {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
   capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -289,21 +300,23 @@
 
   __user_cap_data_struct capdata[2];
   if (capget(&capheader, &capdata[0]) == -1) {
-    ALOGE("capget failed: %s", strerror(errno));
-    RuntimeAbort(env, __LINE__, "capget failed");
+    *error_msg = CREATE_ERROR("capget failed: %s", strerror(errno));
+    return false;
   }
 
   capdata[0].inheritable = inheritable;
   capdata[1].inheritable = inheritable >> 32;
 
   if (capset(&capheader, &capdata[0]) == -1) {
-    ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
-    RuntimeAbort(env, __LINE__, "capset failed");
+    *error_msg = CREATE_ERROR("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
+    return false;
   }
+
+  return true;
 }
 
-static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective,
-                            uint64_t inheritable) {
+static bool SetCapabilities(uint64_t permitted, uint64_t effective, uint64_t inheritable,
+                            std::string* error_msg) {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
   capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -319,18 +332,20 @@
   capdata[1].inheritable = inheritable >> 32;
 
   if (capset(&capheader, &capdata[0]) == -1) {
-    ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted,
-          effective, inheritable, strerror(errno));
-    RuntimeAbort(env, __LINE__, "capset failed");
+    *error_msg = CREATE_ERROR("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") "
+                              "failed: %s", permitted, effective, inheritable, strerror(errno));
+    return false;
   }
+  return true;
 }
 
-static void SetSchedulerPolicy(JNIEnv* env) {
+static bool SetSchedulerPolicy(std::string* error_msg) {
   errno = -set_sched_policy(0, SP_DEFAULT);
   if (errno != 0) {
-    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
-    RuntimeAbort(env, __LINE__, "set_sched_policy(0, SP_DEFAULT) failed");
+    *error_msg = CREATE_ERROR("set_sched_policy(0, SP_DEFAULT) failed: %s", strerror(errno));
+    return false;
   }
+  return true;
 }
 
 static int UnmountTree(const char* path) {
@@ -364,7 +379,7 @@
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
-        bool force_mount_namespace) {
+        bool force_mount_namespace, std::string* error_msg) {
     // See storage config details at http://source.android.com/tech/storage/
 
     String8 storageSource;
@@ -381,7 +396,7 @@
 
     // Create a second private mount namespace for our process
     if (unshare(CLONE_NEWNS) == -1) {
-        ALOGW("Failed to unshare(): %s", strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to unshare(): %s", strerror(errno));
         return false;
     }
 
@@ -392,7 +407,9 @@
 
     if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
             NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
-        ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+                                  storageSource.string(),
+                                  strerror(errno));
         return false;
     }
 
@@ -400,11 +417,14 @@
     userid_t user_id = multiuser_get_user_id(uid);
     const String8 userSource(String8::format("/mnt/user/%d", user_id));
     if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
         return false;
     }
     if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
             NULL, MS_BIND, NULL)) == -1) {
-        ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+                                  userSource.string(),
+                                  strerror(errno));
         return false;
     }
 
@@ -436,31 +456,32 @@
 // descriptor (if any) is closed via dup2(), replacing it with a valid
 // (open) descriptor to /dev/null.
 
-static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+static bool DetachDescriptors(JNIEnv* env, jintArray fdsToClose, std::string* error_msg) {
   if (!fdsToClose) {
-    return;
+    return true;
   }
   jsize count = env->GetArrayLength(fdsToClose);
   ScopedIntArrayRO ar(env, fdsToClose);
   if (ar.get() == NULL) {
-      RuntimeAbort(env, __LINE__, "Bad fd array");
+    *error_msg = "Bad fd array";
+    return false;
   }
   jsize i;
   int devnull;
   for (i = 0; i < count; i++) {
     devnull = open("/dev/null", O_RDWR);
     if (devnull < 0) {
-      ALOGE("Failed to open /dev/null: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Failed to open /dev/null");
-      continue;
+      *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
+      return false;
     }
     ALOGV("Switching descriptor %d to /dev/null: %s", ar[i], strerror(errno));
     if (dup2(devnull, ar[i]) < 0) {
-      ALOGE("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
-      RuntimeAbort(env, __LINE__, "Failed dup2()");
+      *error_msg = StringPrintf("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
+      return false;
     }
     close(devnull);
   }
+  return true;
 }
 
 void SetThreadName(const char* thread_name) {
@@ -495,20 +516,23 @@
 // The list of open zygote file descriptors.
 static FileDescriptorTable* gOpenFdTable = NULL;
 
-static void FillFileDescriptorVector(JNIEnv* env,
+static bool FillFileDescriptorVector(JNIEnv* env,
                                      jintArray java_fds,
-                                     std::vector<int>* fds) {
+                                     std::vector<int>* fds,
+                                     std::string* error_msg) {
   CHECK(fds != nullptr);
   if (java_fds != nullptr) {
     ScopedIntArrayRO ar(env, java_fds);
     if (ar.get() == nullptr) {
-      RuntimeAbort(env, __LINE__, "Bad fd array");
+      *error_msg = "Bad fd array";
+      return false;
     }
     fds->reserve(ar.size());
     for (size_t i = 0; i < ar.size(); ++i) {
       fds->push_back(ar[i]);
     }
   }
+  return true;
 }
 
 // Utility routine to fork zygote and specialize the child process.
@@ -526,32 +550,53 @@
   sigemptyset(&sigchld);
   sigaddset(&sigchld, SIGCHLD);
 
+  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
+      __attribute__ ((noreturn)) {
+    const char* se_name_c_str = nullptr;
+    std::unique_ptr<ScopedUtfChars> se_name;
+    if (java_se_name != nullptr) {
+      se_name.reset(new ScopedUtfChars(env, java_se_name));
+      se_name_c_str = se_name->c_str();
+    }
+    if (se_name_c_str == nullptr && is_system_server) {
+      se_name_c_str = "system_server";
+    }
+    const std::string& error_msg = (se_name_c_str == nullptr)
+        ? msg
+        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
+    env->FatalError(error_msg.c_str());
+    __builtin_unreachable();
+  };
+
   // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
   // log, which would result in the logging FDs we close being reopened.
   // This would cause failures because the FDs are not whitelisted.
   //
   // Note that the zygote process is single threaded at this point.
   if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
-    ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-    RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
+    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
   }
 
   // Close any logging related FDs before we start evaluating the list of
   // file descriptors.
   __android_log_close();
 
+  std::string error_msg;
+
   // If this is the first fork for this zygote, create the open FD table.
   // If it isn't, we just need to check whether the list of open files has
   // changed (and it shouldn't in the normal case).
   std::vector<int> fds_to_ignore;
-  FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
+  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
+  }
   if (gOpenFdTable == NULL) {
-    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
     if (gOpenFdTable == NULL) {
-      RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
+      fail_fn(error_msg);
     }
-  } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
-    RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
+  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
   }
 
   pid_t pid = fork();
@@ -560,17 +605,18 @@
     PreApplicationInit();
 
     // Clean up any descriptors which must be closed immediately
-    DetachDescriptors(env, fdsToClose);
+    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
     // Re-open all remaining open file descriptors so that they aren't shared
     // with the zygote across a fork.
-    if (!gOpenFdTable->ReopenOrDetach()) {
-      RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
+    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
+      fail_fn(error_msg);
     }
 
     if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
-      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
     }
 
     // Must be called when the new process still has CAP_SYS_ADMIN.  The other alternative is to
@@ -580,11 +626,17 @@
 
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
-      EnableKeepCapabilities(env);
+      if (!EnableKeepCapabilities(&error_msg)) {
+        fail_fn(error_msg);
+      }
     }
 
-    SetInheritable(env, permittedCapabilities);
-    DropCapabilitiesBoundingSet(env);
+    if (!SetInheritable(permittedCapabilities, &error_msg)) {
+      fail_fn(error_msg);
+    }
+    if (!DropCapabilitiesBoundingSet(&error_msg)) {
+      fail_fn(error_msg);
+    }
 
     bool use_native_bridge = !is_system_server && (instructionSet != NULL)
         && android::NativeBridgeAvailable();
@@ -601,8 +653,8 @@
       ALOGW("Native bridge will not be used because dataDir == NULL.");
     }
 
-    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
-      ALOGW("Failed to mount emulated storage: %s", strerror(errno));
+    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) {
+      ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
       if (errno == ENOTCONN || errno == EROFS) {
         // When device is actively encrypting, we get ENOTCONN here
         // since FUSE was mounted before the framework restarted.
@@ -610,7 +662,7 @@
         // FUSE hasn't been created yet by init.
         // In either case, continue without external storage.
       } else {
-        RuntimeAbort(env, __LINE__, "Cannot continue without emulated storage");
+        fail_fn(error_msg);
       }
     }
 
@@ -625,9 +677,14 @@
         }
     }
 
-    SetGids(env, javaGids);
+    std::string error_msg;
+    if (!SetGids(env, javaGids, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
-    SetRLimits(env, javaRlimits);
+    if (!SetRLimits(env, javaRlimits, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
     if (use_native_bridge) {
       ScopedUtfChars isa_string(env, instructionSet);
@@ -637,14 +694,12 @@
 
     int rc = setresgid(gid, gid, gid);
     if (rc == -1) {
-      ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
-      RuntimeAbort(env, __LINE__, "setresgid failed");
+      fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
     }
 
     rc = setresuid(uid, uid, uid);
     if (rc == -1) {
-      ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
-      RuntimeAbort(env, __LINE__, "setresuid failed");
+      fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
     }
 
     if (NeedsNoRandomizeWorkaround()) {
@@ -656,9 +711,14 @@
         }
     }
 
-    SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
+    if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
+                         &error_msg)) {
+      fail_fn(error_msg);
+    }
 
-    SetSchedulerPolicy(env);
+    if (!SetSchedulerPolicy(&error_msg)) {
+      fail_fn(error_msg);
+    }
 
     const char* se_info_c_str = NULL;
     ScopedUtfChars* se_info = NULL;
@@ -666,7 +726,7 @@
         se_info = new ScopedUtfChars(env, java_se_info);
         se_info_c_str = se_info->c_str();
         if (se_info_c_str == NULL) {
-          RuntimeAbort(env, __LINE__, "se_info_c_str == NULL");
+          fail_fn("se_info_c_str == NULL");
         }
     }
     const char* se_name_c_str = NULL;
@@ -675,14 +735,13 @@
         se_name = new ScopedUtfChars(env, java_se_name);
         se_name_c_str = se_name->c_str();
         if (se_name_c_str == NULL) {
-          RuntimeAbort(env, __LINE__, "se_name_c_str == NULL");
+          fail_fn("se_name_c_str == NULL");
         }
     }
     rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
     if (rc == -1) {
-      ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
-            is_system_server, se_info_c_str, se_name_c_str);
-      RuntimeAbort(env, __LINE__, "selinux_android_setcontext failed");
+      fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+            is_system_server, se_info_c_str, se_name_c_str));
     }
 
     // Make it easier to debug audit logs by setting the main thread's name to the
@@ -703,15 +762,14 @@
     env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                               is_system_server, is_child_zygote, instructionSet);
     if (env->ExceptionCheck()) {
-      RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
+      fail_fn("Error calling post fork hooks.");
     }
   } else if (pid > 0) {
     // the parent process
 
     // We blocked SIGCHLD prior to a fork, we unblock it here.
     if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
-      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
     }
   }
   return pid;
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 2e60582..c5904e0 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -123,14 +123,57 @@
 
 FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
 
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+  // Create a FileDescriptorInfo for a given file descriptor. Returns
+  // |NULL| if an error occurred.
+  static FileDescriptorInfo* CreateFromFd(int fd, std::string* error_msg);
+
+  // Checks whether the file descriptor associated with this object
+  // refers to the same description.
+  bool Restat() const;
+
+  bool ReopenOrDetach(std::string* error_msg) const;
+
+  const int fd;
+  const struct stat stat;
+  const std::string file_path;
+  const int open_flags;
+  const int fd_flags;
+  const int fs_flags;
+  const off_t offset;
+  const bool is_sock;
+
+ private:
+  FileDescriptorInfo(int fd);
+
+  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+                     int fd_flags, int fs_flags, off_t offset);
+
+  // Returns the locally-bound name of the socket |fd|. Returns true
+  // iff. all of the following hold :
+  //
+  // - the socket's sa_family is AF_UNIX.
+  // - the length of the path is greater than zero (i.e, not an unnamed socket).
+  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+  //   address).
+  static bool GetSocketName(const int fd, std::string* result);
+
+  bool DetachSocket(std::string* error_msg) const;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
 // static
-FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
+FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, std::string* error_msg) {
   struct stat f_stat;
   // This should never happen; the zygote should always have the right set
   // of permissions required to stat all its open files.
   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
-    PLOG(ERROR) << "Unable to stat fd " << fd;
-    return NULL;
+    *error_msg = android::base::StringPrintf("Unable to stat %d", fd);
+    return nullptr;
   }
 
   const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
@@ -138,13 +181,15 @@
   if (S_ISSOCK(f_stat.st_mode)) {
     std::string socket_name;
     if (!GetSocketName(fd, &socket_name)) {
-      return NULL;
+      *error_msg = "Unable to get socket name";
+      return nullptr;
     }
 
     if (!whitelist->IsAllowed(socket_name)) {
-      LOG(ERROR) << "Socket name not whitelisted : " << socket_name
-                 << " (fd=" << fd << ")";
-      return NULL;
+      *error_msg = android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
+                                               socket_name.c_str(),
+                                               fd);
+      return nullptr;
     }
 
     return new FileDescriptorInfo(fd);
@@ -161,19 +206,22 @@
   // with the child process across forks but those should have been closed
   // before we got to this point.
   if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
-    LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
-    return NULL;
+    *error_msg = android::base::StringPrintf("Unsupported st_mode %u", f_stat.st_mode);
+    return nullptr;
   }
 
   std::string file_path;
   const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
   if (!android::base::Readlink(fd_path, &file_path)) {
-    return NULL;
+    *error_msg = android::base::StringPrintf("Could not read fd link %s: %s",
+                                             fd_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   if (!whitelist->IsAllowed(file_path)) {
-    LOG(ERROR) << "Not whitelisted : " << file_path;
-    return NULL;
+    *error_msg = std::string("Not whitelisted : ").append(file_path);
+    return nullptr;
   }
 
   // File descriptor flags : currently on FD_CLOEXEC. We can set these
@@ -181,8 +229,11 @@
   // there won't be any races.
   const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
   if (fd_flags == -1) {
-    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
-    return NULL;
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
+                                             fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   // File status flags :
@@ -199,8 +250,11 @@
   //   their presence and pass them in to open().
   int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
   if (fs_flags == -1) {
-    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
-    return NULL;
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
+                                             fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   // File offset : Ignore the offset for non seekable files.
@@ -225,9 +279,9 @@
   return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
 }
 
-bool FileDescriptorInfo::ReopenOrDetach() const {
+bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const {
   if (is_sock) {
-    return DetachSocket();
+    return DetachSocket(error_msg);
   }
 
   // NOTE: This might happen if the file was unlinked after being opened.
@@ -236,31 +290,49 @@
   const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
 
   if (new_fd == -1) {
-    PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed open(%s, %i): %s",
+                                             file_path.c_str(),
+                                             open_flags,
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
+                                             new_fd,
+                                             fd_flags,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
+                                             new_fd,
+                                             fs_flags,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
+    *error_msg = android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
+                                             new_fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
+    *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s",
+                                             fd,
+                                             new_fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
@@ -336,20 +408,22 @@
   return true;
 }
 
-bool FileDescriptorInfo::DetachSocket() const {
+bool FileDescriptorInfo::DetachSocket(std::string* error_msg) const {
   const int dev_null_fd = open("/dev/null", O_RDWR);
   if (dev_null_fd < 0) {
-    PLOG(ERROR) << "Failed to open /dev/null";
+    *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
     return false;
   }
 
   if (dup2(dev_null_fd, fd) == -1) {
-    PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
+    *error_msg = android::base::StringPrintf("Failed dup2 on socket descriptor %d: %s",
+                                             fd,
+                                             strerror(errno));
     return false;
   }
 
   if (close(dev_null_fd) == -1) {
-    PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
+    *error_msg = android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno));
     return false;
   }
 
@@ -357,11 +431,12 @@
 }
 
 // static
-FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
+                                                 std::string* error_msg) {
   DIR* d = opendir(kFdPath);
-  if (d == NULL) {
-    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
-    return NULL;
+  if (d == nullptr) {
+    *error_msg = std::string("Unable to open directory ").append(kFdPath);
+    return nullptr;
   }
   int dir_fd = dirfd(d);
   dirent* e;
@@ -377,7 +452,7 @@
       continue;
     }
 
-    FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+    FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
     if (info == NULL) {
       if (closedir(d) == -1) {
         PLOG(ERROR) << "Unable to close directory";
@@ -388,19 +463,21 @@
   }
 
   if (closedir(d) == -1) {
-    PLOG(ERROR) << "Unable to close directory";
-    return NULL;
+    *error_msg = "Unable to close directory";
+    return nullptr;
   }
   return new FileDescriptorTable(open_fd_map);
 }
 
-bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg) {
   std::set<int> open_fds;
 
   // First get the list of open descriptors.
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
-    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
+    *error_msg = android::base::StringPrintf("Unable to open directory %s: %s",
+                                             kFdPath,
+                                             strerror(errno));
     return false;
   }
 
@@ -420,21 +497,21 @@
   }
 
   if (closedir(d) == -1) {
-    PLOG(ERROR) << "Unable to close directory";
+    *error_msg = android::base::StringPrintf("Unable to close directory: %s", strerror(errno));
     return false;
   }
 
-  return RestatInternal(open_fds);
+  return RestatInternal(open_fds, error_msg);
 }
 
 // Reopens all file descriptors that are contained in the table. Returns true
 // if all descriptors were successfully re-opened or detached, and false if an
 // error occurred.
-bool FileDescriptorTable::ReopenOrDetach() {
+bool FileDescriptorTable::ReopenOrDetach(std::string* error_msg) {
   std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
   for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
     const FileDescriptorInfo* info = it->second;
-    if (info == NULL || !info->ReopenOrDetach()) {
+    if (info == NULL || !info->ReopenOrDetach(error_msg)) {
       return false;
     }
   }
@@ -447,7 +524,7 @@
     : open_fd_map_(map) {
 }
 
-bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) {
+bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds, std::string* error_msg) {
   bool error = false;
 
   // Iterate through the list of file descriptors we've already recorded
@@ -455,6 +532,8 @@
   //
   // (a) they continue to be open.
   // (b) they refer to the same file.
+  //
+  // We'll only store the last error message.
   std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
   while (it != open_fd_map_.end()) {
     std::set<int>::const_iterator element = open_fds.find(it->first);
@@ -475,7 +554,7 @@
         // The file descriptor refers to a different description. We must
         // update our entry in the table.
         delete it->second;
-        it->second = FileDescriptorInfo::CreateFromFd(*element);
+        it->second = FileDescriptorInfo::CreateFromFd(*element, error_msg);
         if (it->second == NULL) {
           // The descriptor no longer no longer refers to a whitelisted file.
           // We flag an error and remove it from the list of files we're
@@ -510,7 +589,7 @@
     std::set<int>::const_iterator it;
     for (it = open_fds.begin(); it != open_fds.end(); ++it) {
       const int fd = (*it);
-      FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+      FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
       if (info == NULL) {
         // A newly opened file is not on the whitelist. Flag an error and
         // continue.
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a39e387..a3570d7 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -28,6 +28,8 @@
 
 #include <android-base/macros.h>
 
+class FileDescriptorInfo;
+
 // Whitelist of open paths that the zygote is allowed to keep open.
 //
 // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and
@@ -66,49 +68,6 @@
   DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist);
 };
 
-// Keeps track of all relevant information (flags, offset etc.) of an
-// open zygote file descriptor.
-class FileDescriptorInfo {
- public:
-  // Create a FileDescriptorInfo for a given file descriptor. Returns
-  // |NULL| if an error occurred.
-  static FileDescriptorInfo* CreateFromFd(int fd);
-
-  // Checks whether the file descriptor associated with this object
-  // refers to the same description.
-  bool Restat() const;
-
-  bool ReopenOrDetach() const;
-
-  const int fd;
-  const struct stat stat;
-  const std::string file_path;
-  const int open_flags;
-  const int fd_flags;
-  const int fs_flags;
-  const off_t offset;
-  const bool is_sock;
-
- private:
-  FileDescriptorInfo(int fd);
-
-  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
-                     int fd_flags, int fs_flags, off_t offset);
-
-  // Returns the locally-bound name of the socket |fd|. Returns true
-  // iff. all of the following hold :
-  //
-  // - the socket's sa_family is AF_UNIX.
-  // - the length of the path is greater than zero (i.e, not an unnamed socket).
-  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
-  //   address).
-  static bool GetSocketName(const int fd, std::string* result);
-
-  bool DetachSocket() const;
-
-  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
-};
-
 // A FileDescriptorTable is a collection of FileDescriptorInfo objects
 // keyed by their FDs.
 class FileDescriptorTable {
@@ -116,19 +75,20 @@
   // Creates a new FileDescriptorTable. This function scans
   // /proc/self/fd for the list of open file descriptors and collects
   // information about them. Returns NULL if an error occurs.
-  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
+  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore,
+                                     std::string* error_msg);
 
-  bool Restat(const std::vector<int>& fds_to_ignore);
+  bool Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg);
 
   // Reopens all file descriptors that are contained in the table. Returns true
   // if all descriptors were successfully re-opened or detached, and false if an
   // error occurred.
-  bool ReopenOrDetach();
+  bool ReopenOrDetach(std::string* error_msg);
 
  private:
   FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
 
-  bool RestatInternal(std::set<int>& open_fds);
+  bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
 
   static int ParseFd(dirent* e, int dir_fd);
 
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 914a7db..23c5661 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -56,388 +56,455 @@
     optional SettingProto enable_accessibility_global_gesture_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto airplane_mode_on = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto theater_mode_on = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    reserved 6,7,8,9,10; // Accidentally used. They are currently free to be reused.
     // A comma-separated list of radios that need to be disabled when airplane
     // mode is on. This overrides wifi_on and bluetooth_on if wifi and bluetooth
     // are included in the comma-separated list.
-    optional SettingProto airplane_mode_radios = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto airplane_mode_toggleable_radios = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_class_of_device = 293 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_disabled_profiles = 13;
-    optional SettingProto bluetooth_interoperability_list = 14;
-    optional SettingProto wifi_sleep_policy = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto auto_time = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto auto_time_zone = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto car_dock_sound = 18;
-    optional SettingProto car_undock_sound = 19;
-    optional SettingProto desk_dock_sound = 20;
-    optional SettingProto desk_undock_sound = 21;
-    optional SettingProto dock_sounds_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dock_sounds_enabled_when_accessibility = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_sound = 24;
-    optional SettingProto unlock_sound = 25;
-    optional SettingProto trusted_sound = 26;
-    optional SettingProto low_battery_sound = 27;
-    optional SettingProto power_sounds_enabled = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wireless_charging_started_sound = 29;
-    optional SettingProto charging_sounds_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto stay_on_while_plugged_in = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bugreport_in_power_menu = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto adb_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto airplane_mode_radios = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto airplane_mode_toggleable_radios = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto bluetooth_class_of_device = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto bluetooth_disabled_profiles = 9;
+    optional SettingProto bluetooth_interoperability_list = 10;
+    optional SettingProto wifi_sleep_policy = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto auto_time = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto auto_time_zone = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto car_dock_sound = 14;
+    optional SettingProto car_undock_sound = 15;
+    optional SettingProto desk_dock_sound = 16;
+    optional SettingProto desk_undock_sound = 17;
+    optional SettingProto dock_sounds_enabled = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dock_sounds_enabled_when_accessibility = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_sound = 20;
+    optional SettingProto unlock_sound = 21;
+    optional SettingProto trusted_sound = 22;
+    optional SettingProto low_battery_sound = 23;
+    optional SettingProto power_sounds_enabled = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wireless_charging_started_sound = 25;
+    optional SettingProto charging_sounds_enabled = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto stay_on_while_plugged_in = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto bugreport_in_power_menu = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto adb_enabled = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether views are allowed to save their attribute data.
-    optional SettingProto debug_view_attributes = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assisted_gps_enabled = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_on = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto cdma_cell_broadcast_sms = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto cdma_roaming_mode = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto cdma_subscription_mode = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto data_activity_timeout_mobile = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto data_activity_timeout_wifi = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto data_roaming = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mdc_initial_max_retry = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto force_allow_on_external = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto euicc_provisioned = 294 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto development_force_resizable_activities = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto development_enable_freeform_windows_support = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto development_settings_enabled = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto device_provisioned = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto device_provisioning_mobile_data_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto display_size_forced = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto display_scaling_force = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto download_max_bytes_over_mobile = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto download_recommended_max_bytes_over_mobile = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hdmi_control_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hdmi_system_audio_control_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hdmi_control_auto_wakeup_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hdmi_control_auto_device_off_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto location_background_throttle_interval_ms = 295 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto location_background_throttle_proximity_alert_interval_ms = 296 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto debug_view_attributes = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assisted_gps_enabled = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto bluetooth_on = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto cdma_cell_broadcast_sms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto cdma_roaming_mode = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto cdma_subscription_mode = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto data_activity_timeout_mobile = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto data_activity_timeout_wifi = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto data_roaming = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mdc_initial_max_retry = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto force_allow_on_external = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto euicc_provisioned = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto development_force_resizable_activities = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto development_enable_freeform_windows_support = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto development_settings_enabled = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto device_provisioned = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto device_provisioning_mobile_data_enabled = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto display_size_forced = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto display_scaling_force = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto download_max_bytes_over_mobile = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto download_recommended_max_bytes_over_mobile = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hdmi_control_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hdmi_system_audio_control_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hdmi_control_auto_wakeup_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hdmi_control_auto_device_off_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // If true, out-of-the-box execution for priv apps is enabled.
+    optional SettingProto priv_app_oob_enabled = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto location_background_throttle_interval_ms = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto location_background_throttle_proximity_alert_interval_ms = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Packages that are whitelisted for background throttling (throttling will
     // not be applied).
-    optional SettingProto location_background_throttle_package_whitelist = 297 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_scan_background_throttle_interval_ms = 298 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_scan_background_throttle_package_whitelist = 299 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mhl_input_switching_enabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mhl_power_charge_enabled = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mobile_data = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mobile_data_always_on = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto connectivity_metrics_buffer_size = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_poll_interval = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_time_cache_max_age = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_global_alert_bytes = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_sample_enabled = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_augment_enabled = 300 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_dev_bucket_duration = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_dev_persist_bytes = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_dev_rotate_age = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_dev_delete_age = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_bucket_duration = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_persist_bytes = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_rotate_age = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_delete_age = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_tag_bucket_duration = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_tag_persist_bytes = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_tag_rotate_age = 78 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto netstats_uid_tag_delete_age = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto location_background_throttle_package_whitelist = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_scan_background_throttle_interval_ms = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_scan_background_throttle_package_whitelist = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mhl_input_switching_enabled = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mhl_power_charge_enabled = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mobile_data = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mobile_data_always_on = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto connectivity_metrics_buffer_size = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_enabled = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_poll_interval = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_time_cache_max_age = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_global_alert_bytes = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_sample_enabled = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_augment_enabled = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_dev_bucket_duration = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_dev_persist_bytes = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_dev_rotate_age = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_dev_delete_age = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_bucket_duration = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_persist_bytes = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_rotate_age = 78 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_delete_age = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_tag_bucket_duration = 80 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_tag_persist_bytes = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_tag_rotate_age = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto netstats_uid_tag_delete_age = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // User preference for which network(s) should be used.
-    optional SettingProto network_preference = 80;
-    optional SettingProto network_scorer_app = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto nitz_update_diff = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto nitz_update_spacing = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto ntp_server = 84;
-    optional SettingProto ntp_timeout = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto storage_benchmark_interval = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dns_resolver_sample_validity_seconds = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dns_resolver_success_threshold_percent = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dns_resolver_min_samples = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dns_resolver_max_samples = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_preference = 84;
+    optional SettingProto network_scorer_app = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_forced_auto_mode_available = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto nitz_update_diff = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto nitz_update_spacing = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ntp_server = 89;
+    optional SettingProto ntp_timeout = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto storage_benchmark_interval = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dns_resolver_sample_validity_seconds = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dns_resolver_success_threshold_percent = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dns_resolver_min_samples = 94 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dns_resolver_max_samples = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether to disable the automatic scheduling of system updates.
-    optional SettingProto ota_disable_automatic_update = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_enable = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_timeout = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_default_response = 94;
-    optional SettingProto package_verifier_setting_visible = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_include_adb = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto fstrim_mandatory_interval = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_poll_interval_ms = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_long_poll_interval_ms = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_error_poll_interval_ms = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_trigger_packet_count = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_error_poll_count = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto setup_prepaid_data_service_url = 105;
-    optional SettingProto setup_prepaid_detection_target_url = 106;
-    optional SettingProto setup_prepaid_detection_redir_host = 107;
-    optional SettingProto sms_outgoing_check_interval_ms = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sms_outgoing_check_max_count = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ota_disable_automatic_update = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_enable = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_timeout = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_default_response = 99;
+    optional SettingProto package_verifier_setting_visible = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_include_adb = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto fstrim_mandatory_interval = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_poll_interval_ms = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_long_poll_interval_ms = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_error_poll_interval_ms = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_trigger_packet_count = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_error_poll_count = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pdp_watchdog_max_pdp_reset_fail_count = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto setup_prepaid_data_service_url = 109;
+    optional SettingProto setup_prepaid_detection_target_url = 110;
+    optional SettingProto setup_prepaid_detection_redir_host = 111;
+    optional SettingProto sms_outgoing_check_interval_ms = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sms_outgoing_check_max_count = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Used to disable SMS short code confirmation. Defaults to true.
-    optional SettingProto sms_short_code_confirmation = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sms_short_code_rule = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tcp_default_init_rwnd = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tether_supported = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tether_dun_required = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tether_dun_apn = 115;
-    optional SettingProto tether_offload_disabled = 301 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sms_short_code_confirmation = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sms_short_code_rule = 115 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tcp_default_init_rwnd = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tether_supported = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tether_dun_required = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tether_dun_apn = 119;
+    optional SettingProto tether_offload_disabled = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // List of carrier app certificate mapped to carrier app package id which are whitelisted to
     // prompt the user for install when a SIM card with matching UICC carrier privilege rules is
     // inserted.
-    optional SettingProto carrier_app_whitelist = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto carrier_app_names = 358 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto usb_mass_storage_enabled = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto use_google_mail = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto webview_data_reduction_proxy_key = 119;
-    optional SettingProto webview_fallback_logic_enabled = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto carrier_app_whitelist = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto carrier_app_names = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto usb_mass_storage_enabled = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto use_google_mail = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto webview_data_reduction_proxy_key = 125;
+    optional SettingProto webview_fallback_logic_enabled = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Name of the package used as WebView provider.
-    optional SettingProto webview_provider = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto webview_multiprocess = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_switch_notification_daily_limit = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_switch_notification_rate_limit_millis = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_avoid_bad_wifi = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_metered_multipath_preference = 302 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_watchlist_last_report_time = 303 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_badging_thresholds = 304 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_display_on = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_display_certification_on = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_display_wps_config = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_networks_available_notification_on = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wimax_networks_available_notification_on = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_networks_available_repeat_delay = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_country_code = 132;
-    optional SettingProto wifi_framework_scan_interval_ms = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_idle_ms = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_num_open_networks_kept = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_scan_always_available = 137 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_wakeup_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    reserved 305; // Removed wifi_wakeup_available
-    optional SettingProto network_scoring_ui_enabled = 306 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto speed_label_cache_eviction_age_millis = 307 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto recommended_network_evaluator_cache_expiry_ms = 308 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_recommendations_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_recommendations_package = 286 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto use_open_wifi_package = 309 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_recommendation_request_timeout_ms = 310 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto ble_scan_always_available = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_saved_state = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_supplicant_scan_interval_ms = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_enhanced_auto_join = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_network_show_rssi = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_watchdog_on = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_watchdog_poor_network_test_enabled = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_suspend_optimizations_enabled = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_verbose_logging_enabled = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_connected_mac_randomization_enabled = 350 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_max_dhcp_retry_count = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_device_owner_configs_lockdown = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_frequency_band = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_p2p_device_name = 154;
-    optional SettingProto wifi_reenable_delay_ms = 155 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto provisioning_apn_alarm_delay_in_ms = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto gprs_register_check_period_ms = 160 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wtf_is_fatal = 161 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto webview_provider = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto webview_multiprocess = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_switch_notification_daily_limit = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_switch_notification_rate_limit_millis = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_avoid_bad_wifi = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_metered_multipath_preference = 132 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_watchlist_last_report_time = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_badging_thresholds = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_display_on = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_display_certification_on = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_display_wps_config = 137 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_networks_available_notification_on = 138 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_carrier_networks_available_notification_on = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wimax_networks_available_notification_on = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_networks_available_repeat_delay = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_country_code = 142;
+    optional SettingProto wifi_framework_scan_interval_ms = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_idle_ms = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_num_open_networks_kept = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_on = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_scan_always_available = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto soft_ap_timeout_enabled = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_wakeup_enabled = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_scoring_ui_enabled = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto speed_label_cache_eviction_age_millis = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto recommended_network_evaluator_cache_expiry_ms = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_recommendations_enabled = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_recommendations_package = 154 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto use_open_wifi_package = 155 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_recommendation_request_timeout_ms = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_always_available = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_low_power_window_ms = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_balanced_window_ms = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_low_latency_window_ms = 160 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_low_power_interval_ms = 161 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_balanced_interval_ms = 162 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ble_scan_low_latency_interval_ms = 163 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_saved_state = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_supplicant_scan_interval_ms = 165 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_enhanced_auto_join = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_network_show_rssi = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_scan_interval_when_p2p_connected_ms = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_watchdog_on = 169 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_watchdog_poor_network_test_enabled = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_suspend_optimizations_enabled = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_verbose_logging_enabled = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_connected_mac_randomization_enabled = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_max_dhcp_retry_count = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_mobile_data_transition_wakelock_timeout_ms = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_device_owner_configs_lockdown = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_frequency_band = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_p2p_device_name = 178;
+    optional SettingProto wifi_reenable_delay_ms = 179 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_ephemeral_out_of_range_timeout_ms = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto data_stall_alarm_non_aggressive_delay_in_ms = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto data_stall_alarm_aggressive_delay_in_ms = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto provisioning_apn_alarm_delay_in_ms = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto gprs_register_check_period_ms = 184 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wtf_is_fatal = 185 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Ringer mode. A change in this value will not reflect as a change in the
     // ringer mode.
-    optional SettingProto mode_ringer = 162 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mode_ringer = 186 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Overlay display devices setting.
     // The value is a specially formatted string that describes the size and
     // density of simulated secondary devices.
     // Format: {width}x{height}/dpi;...
-    optional SettingProto overlay_display_devices = 163 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto battery_discharge_duration_threshold = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto battery_discharge_threshold = 165 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto send_action_app_error = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_age_seconds = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_max_files = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_quota_kb = 169 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_quota_percent = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_reserve_percent = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dropbox_tag_prefix = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto error_logcat_prefix = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_free_storage_log_interval = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto disk_free_change_reporting_threshold = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_storage_threshold_percentage = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_storage_threshold_max_bytes = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_storage_full_threshold_bytes = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_storage_cache_percentage = 311 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sys_storage_cache_max_bytes = 312 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sync_max_retry_delay_in_seconds = 179 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto connectivity_change_delay = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto connectivity_sampling_interval_in_seconds = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pac_change_delay = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto captive_portal_mode = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto captive_portal_detection_enabled = 313 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto captive_portal_server = 184;
-    optional SettingProto captive_portal_https_url = 185;
-    optional SettingProto captive_portal_http_url = 186;
-    optional SettingProto captive_portal_fallback_url = 187;
-    optional SettingProto captive_portal_other_fallback_urls = 314;
-    optional SettingProto captive_portal_use_https = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto captive_portal_user_agent = 189;
-    optional SettingProto nsd_on = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto overlay_display_devices = 187 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto battery_discharge_duration_threshold = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto battery_discharge_threshold = 189 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto send_action_app_error = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dropbox_age_seconds = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dropbox_max_files = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dropbox_quota_kb = 193 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dropbox_quota_percent = 194 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dropbox_reserve_percent = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    repeated SettingProto dropbox_settings = 196;
+    repeated SettingProto error_logcat_lines = 197;
+    optional SettingProto sys_free_storage_log_interval = 198 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto disk_free_change_reporting_threshold = 199 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sys_storage_threshold_percentage = 200 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sys_storage_threshold_max_bytes = 201 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sys_storage_full_threshold_bytes = 202 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sys_storage_cache_percentage = 203 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sys_storage_cache_max_bytes = 204 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sync_max_retry_delay_in_seconds = 205 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto connectivity_change_delay = 206 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto connectivity_sampling_interval_in_seconds = 207 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pac_change_delay = 208 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto captive_portal_mode = 209 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto captive_portal_detection_enabled = 210 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto captive_portal_server = 211;
+    optional SettingProto captive_portal_https_url = 212;
+    optional SettingProto captive_portal_http_url = 213;
+    optional SettingProto captive_portal_fallback_url = 214;
+    optional SettingProto captive_portal_other_fallback_urls = 215;
+    optional SettingProto captive_portal_use_https = 216 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto captive_portal_user_agent = 217;
+    optional SettingProto nsd_on = 218 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Let user pick default install location.
-    optional SettingProto set_install_location = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto default_install_location = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto inet_condition_debounce_up_delay = 193 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto inet_condition_debounce_down_delay = 194 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto read_external_storage_enforced_default = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto http_proxy = 196;
-    optional SettingProto global_http_proxy_host = 197;
-    optional SettingProto global_http_proxy_port = 198;
-    optional SettingProto global_http_proxy_exclusion_list = 199;
-    optional SettingProto global_http_proxy_pac = 200;
+    optional SettingProto set_install_location = 219 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto default_install_location = 220 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto inet_condition_debounce_up_delay = 221 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto inet_condition_debounce_down_delay = 222 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto read_external_storage_enforced_default = 223 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto http_proxy = 224;
+    optional SettingProto global_http_proxy_host = 225;
+    optional SettingProto global_http_proxy_port = 226;
+    optional SettingProto global_http_proxy_exclusion_list = 227;
+    optional SettingProto global_http_proxy_pac = 228;
     // Enables the UI setting to allow the user to specify the global HTTP proxy
     // and associated exclusion list.
-    optional SettingProto set_global_http_proxy = 201 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto default_dns_server = 202;
+    optional SettingProto set_global_http_proxy = 229 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto default_dns_server = 230;
     // The requested Private DNS mode and an accompanying specifier.
-    optional SettingProto private_dns_mode = 315;
-    optional SettingProto private_dns_specifier = 316;
-    optional SettingProto bluetooth_headset_priority_prefix = 203 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_a2dp_sink_priority_prefix = 204 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_a2dp_src_priority_prefix = 205 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_input_device_priority_prefix = 206 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_map_priority_prefix = 207 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_map_client_priority_prefix = 208 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_pbap_client_priority_prefix = 209 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_sap_priority_prefix = 210 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_pan_priority_prefix = 211 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_hearing_aid_priority_prefix = 345 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto activity_manager_constants = 317;
-    optional SettingProto device_idle_constants = 212;
-    optional SettingProto device_idle_constants_watch = 213;
-    optional SettingProto battery_saver_constants = 318;
-    optional SettingProto anomaly_detection_constants = 319;
-    optional SettingProto always_on_display_constants = 320;
-    optional SettingProto app_idle_constants = 214;
-    optional SettingProto power_manager_constants = 321;
-    optional SettingProto alarm_manager_constants = 215;
-    optional SettingProto job_scheduler_constants = 216;
-    optional SettingProto shortcut_manager_constants = 217;
-    optional SettingProto device_policy_constants = 322;
-    optional SettingProto text_classifier_constants = 323;
-    optional SettingProto window_animation_scale = 218 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto transition_animation_scale = 219 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto animator_duration_scale = 220 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto fancy_ime_animations = 221 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto compatibility_mode = 222 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto emergency_tone = 223 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto call_auto_retry = 224 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto emergency_affordance_needed = 225 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto preferred_network_mode = 226 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto private_dns_mode = 231;
+    optional SettingProto private_dns_specifier = 232;
+    repeated SettingProto bluetooth_headset_priorities = 233;
+    repeated SettingProto bluetooth_a2dp_sink_priorities = 234;
+    repeated SettingProto bluetooth_a2dp_src_priorities = 235;
+    repeated SettingProto bluetooth_a2dp_supports_optional_codecs = 236;
+    repeated SettingProto bluetooth_a2dp_optional_codecs_enabled = 237;
+    repeated SettingProto bluetooth_input_device_priorities = 238;
+    repeated SettingProto bluetooth_map_priorities = 239;
+    repeated SettingProto bluetooth_map_client_priorities = 240;
+    repeated SettingProto bluetooth_pbap_client_priorities = 241;
+    repeated SettingProto bluetooth_sap_priorities = 242;
+    repeated SettingProto bluetooth_pan_priorities = 243;
+    repeated SettingProto bluetooth_hearing_aid_priorities = 244;
+    // These are key=value lists, separated by commas.
+    optional SettingProto activity_manager_constants = 245;
+    optional SettingProto device_idle_constants = 246;
+    optional SettingProto battery_saver_constants = 247;
+    optional SettingProto battery_saver_device_specific_constants = 248;
+    optional SettingProto battery_tip_constants = 249;
+    optional SettingProto anomaly_detection_constants = 250;
+    // Version of the anomaly config.
+    optional SettingProto anomaly_config_version = 251 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // A base64-encoded string represents anomaly stats config.
+    optional SettingProto anomaly_config = 252;
+    // This is a key=value list, separated by commas.
+    optional SettingProto always_on_display_constants = 253;
+    // System VDSO global setting. This links to the "sys.vdso" system property.
+    // The following values are supported:
+    // false  -> both 32 and 64 bit vdso disabled
+    // 32     -> 32 bit vdso enabled
+    // 64     -> 64 bit vdso enabled
+    // Any other value defaults to both 32 bit and 64 bit true.
+    optional SettingProto sys_vdso = 254 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // UidCpuPower global setting. This links the sys.uidcpupower system property.
+    // The following values are supported:
+    // 0 -> /proc/uid_cpupower/* are disabled
+    // 1 -> /proc/uid_cpupower/* are enabled
+    // Any other value defaults to enabled.
+    optional SettingProto sys_uidcpupower = 255 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // An integer to reduce the FPS by this factor. Only for experiments.
+    optional SettingProto fps_divisor = 256 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // Flag to enable or disable display panel low power mode (lpm)
+    // false -> Display panel power saving mode is disabled.
+    // true  -> Display panel power saving mode is enabled.
+    optional SettingProto display_panel_lpm = 257 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // These are key=value lists, separated by commas.
+    optional SettingProto app_idle_constants = 258;
+    optional SettingProto power_manager_constants = 259;
+    optional SettingProto alarm_manager_constants = 260;
+    optional SettingProto job_scheduler_constants = 261;
+    optional SettingProto shortcut_manager_constants = 262;
+    optional SettingProto device_policy_constants = 263;
+    optional SettingProto text_classifier_constants = 264;
+    optional SettingProto battery_stats_constants = 265;
+    optional SettingProto sync_manager_constants = 266;
+    optional SettingProto app_standby_enabled = 267 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto app_auto_restriction_enabled = 268 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto forced_app_standby_enabled = 269 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto forced_app_standby_for_small_battery_enabled = 270 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto off_body_radios_off_for_small_battery_enabled = 271 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto off_body_radios_off_delay_ms = 272 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_on_when_proxy_disconnected = 273 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto time_only_mode_enabled = 274 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_watchlist_enabled = 275 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto keep_profile_in_background = 276 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto window_animation_scale = 277 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto transition_animation_scale = 278 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto animator_duration_scale = 279 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto fancy_ime_animations = 280 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto compatibility_mode = 281 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto emergency_tone = 282 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto call_auto_retry = 283 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto emergency_affordance_needed = 284 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto preferred_network_mode = 285 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Name of an application package to be debugged.
-    optional SettingProto debug_app = 227;
-    optional SettingProto wait_for_debugger = 228 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_gpu_debug_layers = 342 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto debug_app = 286;
+    optional SettingProto wait_for_debugger = 287 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_gpu_debug_layers = 288 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // App allowed to load GPU debug layers.
-    optional SettingProto gpu_debug_app = 343;
-    optional SettingProto gpu_debug_layers = 344 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto low_power_mode = 229 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto low_power_mode_trigger_level = 230 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto always_finish_activities = 231 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dock_audio_media_enabled = 232 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto encoded_surround_output = 233 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto audio_safe_volume_state = 234 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tzinfo_update_content_url = 235;
-    optional SettingProto tzinfo_update_metadata_url = 236;
-    optional SettingProto selinux_update_content_url = 237;
-    optional SettingProto selinux_update_metadata_url = 238;
-    optional SettingProto sms_short_codes_update_content_url = 239;
-    optional SettingProto sms_short_codes_update_metadata_url = 240;
-    optional SettingProto apn_db_update_content_url = 241;
-    optional SettingProto apn_db_update_metadata_url = 242;
-    optional SettingProto cert_pin_update_content_url = 243;
-    optional SettingProto cert_pin_update_metadata_url = 244;
-    optional SettingProto intent_firewall_update_content_url = 245;
-    optional SettingProto intent_firewall_update_metadata_url = 246;
-    optional SettingProto lang_id_update_content_url = 324;
-    optional SettingProto lang_id_update_metadata_url = 325;
-    optional SettingProto smart_selection_update_content_url = 326;
-    optional SettingProto smart_selection_update_metadata_url = 327;
-    optional SettingProto selinux_status = 247 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto development_force_rtl = 248 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto low_battery_sound_timeout = 249 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wifi_bounce_delay_override_ms = 250 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto policy_control = 251 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto zen_mode = 252 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto zen_mode_ringer_level = 253 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto zen_mode_config_etag = 254;
-    optional SettingProto heads_up_notifications_enabled = 255 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto device_name = 256;
-    optional SettingProto network_scoring_provisioned = 257 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto require_password_to_decrypt = 258 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enhanced_4g_mode_enabled = 259 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto vt_ims_enabled = 260 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wfc_ims_enabled = 261 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wfc_ims_mode = 262 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wfc_ims_roaming_mode = 263 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wfc_ims_roaming_enabled = 264 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lte_service_forced = 265 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto ephemeral_cookie_max_size_bytes = 266 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_ephemeral_feature = 267 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto instant_app_dexopt_enabled = 328 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto installed_instant_app_min_cache_period = 268 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto installed_instant_app_max_cache_period = 289 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto uninstalled_instant_app_min_cache_period = 290 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto uninstalled_instant_app_max_cache_period = 291 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto unused_static_shared_lib_min_cache_period = 292 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto allow_user_switching_when_system_user_locked = 269 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto boot_count = 270 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto safe_boot_disallowed = 271 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto device_demo_mode = 272 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto network_access_timeout_ms = 329 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto database_downgrade_reason = 274;
-    optional SettingProto database_creation_buildid = 330 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto contacts_database_wal_enabled = 275 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto location_settings_link_to_permissions_enabled = 331 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    reserved 332; // Removed backup_refactored_service_disabled
-    optional SettingProto euicc_factory_reset_timeout_millis = 333 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto storage_settings_clobber_threshold = 334 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto chained_battery_attribution_enabled = 353 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hidden_api_blacklist_exemptions = 355 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto gpu_debug_app = 289;
+    optional SettingProto gpu_debug_layers = 290 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto low_power_mode = 291 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // Battery level [1-100] at which low power mode automatically turns on. If
+    // 0, it will not automatically turn on.
+    optional SettingProto low_power_mode_trigger_level = 292 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting
+    // is not set or the value is 0, the default max will be used.
+    optional SettingProto low_power_mode_trigger_level_max = 293 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto always_finish_activities = 294 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dock_audio_media_enabled = 295 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto encoded_surround_output = 296 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto audio_safe_volume_state = 297 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tzinfo_update_content_url = 298;
+    optional SettingProto tzinfo_update_metadata_url = 299;
+    optional SettingProto selinux_update_content_url = 300;
+    optional SettingProto selinux_update_metadata_url = 301;
+    optional SettingProto sms_short_codes_update_content_url = 302;
+    optional SettingProto sms_short_codes_update_metadata_url = 303;
+    optional SettingProto apn_db_update_content_url = 304;
+    optional SettingProto apn_db_update_metadata_url = 305;
+    optional SettingProto cert_pin_update_content_url = 306;
+    optional SettingProto cert_pin_update_metadata_url = 307;
+    optional SettingProto intent_firewall_update_content_url = 308;
+    optional SettingProto intent_firewall_update_metadata_url = 309;
+    optional SettingProto lang_id_update_content_url = 310;
+    optional SettingProto lang_id_update_metadata_url = 311;
+    optional SettingProto smart_selection_update_content_url = 312;
+    optional SettingProto smart_selection_update_metadata_url = 313;
+    optional SettingProto selinux_status = 314 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto development_force_rtl = 315 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto low_battery_sound_timeout = 316 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wifi_bounce_delay_override_ms = 317 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto policy_control = 318 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto emulate_display_cutout = 319 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto zen_mode = 320 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto zen_mode_ringer_level = 321 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto zen_mode_config_etag = 322;
+    // If 0, turning on dnd manually will last indefinitely. Else if
+    // non-negative, turning on dnd manually will last for this many minutes.
+    // Else (if negative), turning on dnd manually will surface a dialog that
+    // prompts user to specify a duration.
+    optional SettingProto zen_duration = 323 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto heads_up_notifications_enabled = 324 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto device_name = 325;
+    optional SettingProto network_scoring_provisioned = 326 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto require_password_to_decrypt = 327 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enhanced_4g_mode_enabled = 328 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vt_ims_enabled = 329 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wfc_ims_enabled = 330 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wfc_ims_mode = 331 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wfc_ims_roaming_mode = 332 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wfc_ims_roaming_enabled = 333 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lte_service_forced = 334 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ephemeral_cookie_max_size_bytes = 335 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_ephemeral_feature = 336 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto instant_app_dexopt_enabled = 337 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto installed_instant_app_min_cache_period = 338 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto installed_instant_app_max_cache_period = 339 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto uninstalled_instant_app_min_cache_period = 340 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto uninstalled_instant_app_max_cache_period = 341 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto unused_static_shared_lib_min_cache_period = 342 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto allow_user_switching_when_system_user_locked = 343 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto boot_count = 344 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto safe_boot_disallowed = 345 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto device_demo_mode = 346 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto network_access_timeout_ms = 347 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto database_downgrade_reason = 348;
+    optional SettingProto database_creation_buildid = 349 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto contacts_database_wal_enabled = 350 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto location_settings_link_to_permissions_enabled = 351 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto euicc_factory_reset_timeout_millis = 352 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto storage_settings_clobber_threshold = 353 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // If set to 1, {@link Secure#LOCATION_MODE} will be set to {@link
+    // Secure#LOCATION_MODE_OFF} temporarily for all users.
+    optional SettingProto location_global_kill_switch = 354 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will
+    // be ignored and restoring to lower version of platform API will be
+    // skipped.
+    optional SettingProto override_settings_provider_restore_any_version = 355 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto chained_battery_attribution_enabled = 356 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_compat_allowed_packages = 357 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hidden_api_blacklist_exemptions = 358 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Subscription to be used for voice call on a multi sim device. The
     // supported values are 0 = SUB1, 1 = SUB2 and etc.
-    optional SettingProto multi_sim_voice_call_subscription = 276 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto multi_sim_voice_prompt = 277 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto multi_sim_data_call_subscription = 278 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto multi_sim_sms_subscription = 279 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto multi_sim_sms_prompt = 280 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_sim_voice_call_subscription = 359 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_sim_voice_prompt = 360 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_sim_data_call_subscription = 361 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_sim_sms_subscription = 362 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_sim_sms_prompt = 363 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether to enable new contacts aggregator or not.
     // 1 = enable, 0 = disable.
-    optional SettingProto new_contact_aggregator = 281 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto contact_metadata_sync_enabled = 282 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_cellular_on_boot = 283 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto max_notification_enqueue_rate = 284 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_notification_channel_warnings = 335 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto cell_on = 285 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_temperature_warning = 336 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto warning_temperature = 337 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_diskstats_logging = 338 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_cache_quota_calculation = 339 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_deletion_helper_no_threshold_toggle = 340 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto notification_snooze_options = 341 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enable_gnss_raw_meas_full_tracking = 346 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto install_carrier_app_notification_persistent = 356 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto install_carrier_app_notification_sleep_millis = 357 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto zram_enabled = 347 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto smart_replies_in_notifications_flags = 348 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_first_crash_dialog = 349 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_restart_in_crash_dialog = 351 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_mute_in_crash_dialog = 352 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingsProto show_zen_upgrade_notification = 354  [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingsProto app_auto_restriction_enabled = 359  [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingsProto zen_duration = 360  [ (android.privacy).dest = DEST_AUTOMATIC ];
-
+    optional SettingProto new_contact_aggregator = 364 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto contact_metadata_sync_enabled = 365 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_cellular_on_boot = 366 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto max_notification_enqueue_rate = 367 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_notification_channel_warnings = 368 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto cell_on = 369 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_temperature_warning = 370 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto warning_temperature = 371 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_diskstats_logging = 372 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_cache_quota_calculation = 373 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_deletion_helper_no_threshold_toggle = 374 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto notification_snooze_options = 375 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // Configuration flags for SQLite Compatibility WAL. Encoded as a key-value
+    // list, separated by commas.
+    // E.g.: compatibility_wal_supported=true, wal_syncmode=OFF
+    optional SettingProto sqlite_compatibility_wal_flags = 376 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enable_gnss_raw_meas_full_tracking = 377 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto install_carrier_app_notification_persistent = 378 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto install_carrier_app_notification_sleep_millis = 379 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto zram_enabled = 380 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto smart_replies_in_notifications_flags = 381 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_first_crash_dialog = 382 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_restart_in_crash_dialog = 383 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_mute_in_crash_dialog = 384 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingsProto show_zen_upgrade_notification = 385  [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Please insert fields in the same order as in
     // frameworks/base/core/java/android/provider/Settings.java.
-    // Next tag = 361;
+    // Next tag = 386;
 }
 
 message SecureSettingsProto {
@@ -454,227 +521,229 @@
     optional SettingProto voice_interaction_service = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The currently selected autofill service flattened ComponentName.
     optional SettingProto autofill_service = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_hci_log = 9;
-    optional SettingProto user_setup_complete = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // Boolean indicating if Autofill supports field classification.
+    optional SettingProto autofill_feature_field_classification = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_user_data_max_user_data_size = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_user_data_max_field_classification_ids_size = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_user_data_max_category_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_user_data_max_value_length = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_user_data_min_value_length = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto user_setup_complete = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether the current user has been set up via setup wizard (0 = false,
     // 1 = true). This value differs from USER_SETUP_COMPLETE in that it can be
     // reset back to 0 in case SetupWizard has been re-enabled on TV devices.
-    optional SettingProto tv_user_setup_complete = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto completed_category_prefix = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enabled_input_methods = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto disabled_system_input_methods = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_ime_with_hard_keyboard = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto always_on_vpn_app = 15;
-    optional SettingProto always_on_vpn_lockdown = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto install_non_market_apps = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto unknown_sources_default_reversed = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tv_user_setup_complete = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    repeated SettingProto completed_categories = 17;
+    optional SettingProto enabled_input_methods = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto disabled_system_input_methods = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_ime_with_hard_keyboard = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto always_on_vpn_app = 21;
+    optional SettingProto always_on_vpn_lockdown = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto install_non_market_apps = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto unknown_sources_default_reversed = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The degree of location access enabled by the user.
-    optional SettingProto location_mode = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto location_previous_mode = 19;
+    optional SettingProto location_mode = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // The App or module that changes the location mode.
+    optional SettingProto location_changer = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether lock-to-app will lock the keyguard when exiting.
-    optional SettingProto lock_to_app_exit_locked = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_screen_lock_after_timeout = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_screen_allow_private_notifications = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_screen_allow_remote_input = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_note_about_notification_hiding = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto trust_agents_initialized = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto parental_control_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto parental_control_last_update = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto parental_control_redirect_url = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto settings_classname = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_enabled = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_shortcut_enabled = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_shortcut_on_lock_screen = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_shortcut_dialog_shown = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_shortcut_target_service = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_to_app_exit_locked = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_screen_lock_after_timeout = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_screen_allow_private_notifications = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_screen_allow_remote_input = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_note_about_notification_hiding = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto trust_agents_initialized = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto parental_control_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto parental_control_last_update = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto parental_control_redirect_url = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto settings_classname = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_enabled = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_shortcut_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_shortcut_on_lock_screen = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_shortcut_dialog_shown = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_shortcut_target_service = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Setting specifying the accessibility service or feature to be toggled via
     // the accessibility button in the navigation bar. This is either a
     // flattened ComponentName or the class name of a system class implementing
     // a supported accessibility feature.
-    optional SettingProto accessibility_button_target_component = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto touch_exploration_enabled = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_button_target_component = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto touch_exploration_enabled = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // List of the enabled accessibility providers.
-    optional SettingProto enabled_accessibility_services = 31;
+    optional SettingProto enabled_accessibility_services = 44;
     // List of the accessibility services to which the user has granted
     // permission to put the device into touch exploration mode.
-    optional SettingProto touch_exploration_granted_accessibility_services = 32;
+    optional SettingProto touch_exploration_granted_accessibility_services = 45;
+    // Uri of the slice that's presented on the keyguard. Defaults to a slice
+    // with the date and next alarm.
+    optional SettingProto keyguard_slice_uri = 46;
     // Whether to speak passwords while in accessibility mode.
-    optional SettingProto accessibility_speak_password = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_high_text_contrast_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_script_injection = 35;
-    optional SettingProto accessibility_screen_reader_url = 36;
-    optional SettingProto accessibility_web_content_key_bindings = 37;
-    optional SettingProto accessibility_display_magnification_enabled = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_magnification_navbar_enabled = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_magnification_scale = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_magnification_auto_update = 179 [deprecated = true];
-    optional SettingProto accessibility_soft_keyboard_mode = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_enabled = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_locale = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_preset = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_background_color = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_foreground_color = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_edge_type = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_edge_color = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_window_color = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_typeface = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_captioning_font_scale = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_inversion_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_daltonizer_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_display_daltonizer = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_autoclick_enabled = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_autoclick_delay = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accessibility_large_pointer_icon = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto long_press_timeout = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto multi_press_timeout = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enabled_print_services = 59;
-    optional SettingProto disabled_print_services = 60;
-    optional SettingProto display_density_forced = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tts_default_rate = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tts_default_pitch = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tts_default_synth = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tts_default_locale = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tts_enabled_plugins = 66;
-    optional SettingProto connectivity_release_pending_intent_delay_ms = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto allowed_geolocation_origins = 68;
-    optional SettingProto preferred_tty_mode = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enhanced_voice_privacy_enabled = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tty_mode_enabled = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_enabled = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_auto_restore = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_provisioned = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_transport = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto last_setup_shown = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_global_search_activity = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_num_promoted_sources = 78 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_max_results_to_display = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_max_results_per_source = 80 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_web_results_override_limit = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_promoted_source_deadline_millis = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_source_timeout_millis = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_prefill_millis = 84 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_max_stat_age_millis = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_max_source_event_age_millis = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_min_impressions_for_source_ranking = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_min_clicks_for_source_ranking = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_max_shortcuts_returned = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_query_thread_core_pool_size = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_query_thread_max_pool_size = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_shortcut_refresh_core_pool_size = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_shortcut_refresh_max_pool_size = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_thread_keepalive_seconds = 94 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto search_per_source_concurrent_query_limit = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_speak_password = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_high_text_contrast_enabled = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_display_magnification_enabled = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_display_magnification_navbar_enabled = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_display_magnification_scale = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_soft_keyboard_mode = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_enabled = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_locale = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_preset = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_background_color = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_foreground_color = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_edge_type = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_edge_color = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_window_color = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_typeface = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_captioning_font_scale = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_display_inversion_enabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_display_daltonizer_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // Integer property that specifies the type of color space adjustment to perform.
+    optional SettingProto accessibility_display_daltonizer = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_autoclick_enabled = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_autoclick_delay = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accessibility_large_pointer_icon = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto long_press_timeout = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto multi_press_timeout = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enabled_print_services = 71;
+    optional SettingProto disabled_print_services = 72;
+    optional SettingProto display_density_forced = 73 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tts_default_rate = 74 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tts_default_pitch = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tts_default_synth = 76 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tts_default_locale = 77 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tts_enabled_plugins = 78;
+    optional SettingProto connectivity_release_pending_intent_delay_ms = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto allowed_geolocation_origins = 80;
+    optional SettingProto preferred_tty_mode = 81 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enhanced_voice_privacy_enabled = 82 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tty_mode_enabled = 83 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_enabled = 84 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_auto_restore = 85 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_provisioned = 86 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_transport = 87 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto last_setup_shown = 88 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_global_search_activity = 89 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_num_promoted_sources = 90 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_max_results_to_display = 91 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_max_results_per_source = 92 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_web_results_override_limit = 93 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_promoted_source_deadline_millis = 94 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_source_timeout_millis = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_prefill_millis = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_max_stat_age_millis = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_max_source_event_age_millis = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_min_impressions_for_source_ranking = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_min_clicks_for_source_ranking = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_max_shortcuts_returned = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_query_thread_core_pool_size = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_query_thread_max_pool_size = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_shortcut_refresh_core_pool_size = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_shortcut_refresh_max_pool_size = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_thread_keepalive_seconds = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto search_per_source_concurrent_query_limit = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether or not alert sounds are played on StorageManagerService events.
-    optional SettingProto mount_play_notification_snd = 96 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mount_ums_autostart = 97 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mount_ums_prompt = 98 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mount_ums_notify_enabled = 99 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto anr_show_background = 100 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mount_play_notification_snd = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mount_ums_autostart = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mount_ums_prompt = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mount_ums_notify_enabled = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto anr_show_background = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_first_crash_dialog_dev_option = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The ComponentName string of the service to be used as the voice
     // recognition service.
-    optional SettingProto voice_recognition_service = 101 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_user_consent = 102 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto selected_spell_checker = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto selected_spell_checker_subtype = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto spell_checker_enabled = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto incall_power_button_behavior = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto incall_back_button_behavior = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto wake_gesture_enabled = 108 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto doze_enabled = 109 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto doze_always_on = 110 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto doze_pulse_on_pick_up = 111 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto doze_pulse_on_long_press = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto doze_pulse_on_double_tap = 112 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto ui_night_mode = 113 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screensaver_enabled = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screensaver_components = 115 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screensaver_activate_on_dock = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screensaver_activate_on_sleep = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screensaver_default_component = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto nfc_payment_default_component = 119 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto nfc_payment_foreground = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sms_default_application = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dialer_default_application = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto emergency_assistance_application = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_structure_enabled = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_screenshot_enabled = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_disclosure_enabled = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto voice_recognition_service = 114 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_user_consent = 115 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto selected_spell_checker = 116 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto selected_spell_checker_subtype = 117 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto spell_checker_enabled = 118 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto incall_power_button_behavior = 119 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto incall_back_button_behavior = 120 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto wake_gesture_enabled = 121 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto doze_enabled = 122 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto doze_always_on = 123 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto doze_pulse_on_pick_up = 124 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto doze_pulse_on_long_press = 125 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto doze_pulse_on_double_tap = 126 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ui_night_mode = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screensaver_enabled = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screensaver_components = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screensaver_activate_on_dock = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screensaver_activate_on_sleep = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screensaver_default_component = 132 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto nfc_payment_default_component = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto nfc_payment_foreground = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sms_default_application = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dialer_default_application = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto emergency_assistance_application = 137 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_structure_enabled = 138 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_screenshot_enabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_disclosure_enabled = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_rotation_suggestions = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto num_rotation_suggestions_accepted = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Read only list of the service components that the current user has
     // explicitly allowed to see and assist with all of the user's
     // notifications.
-    optional SettingProto enabled_notification_assistant = 127 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enabled_notification_listeners = 128 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto enabled_notification_policy_access_packages = 129 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enabled_notification_assistant = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enabled_notification_listeners = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enabled_notification_policy_access_packages = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Defines whether managed profile ringtones should be synced from its
     // parent profile.
-    optional SettingProto sync_parent_sounds = 130 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto immersive_mode_confirmations = 131 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sync_parent_sounds = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto immersive_mode_confirmations = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The query URI to find a print service to install.
-    optional SettingProto print_service_search_uri = 132 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto print_service_search_uri = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The query URI to find an NFC service to install.
-    optional SettingProto payment_service_search_uri = 133 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto payment_service_search_uri = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The query URI to find an auto fill service to install.
-    optional SettingProto autofill_service_search_uri = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto skip_first_use_hints = 134 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto unsafe_volume_music_active_ms = 135 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_screen_show_notifications = 136 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tv_input_hidden_inputs = 137;
-    optional SettingProto tv_input_custom_labels = 138;
-    optional SettingProto usb_audio_automatic_routing_disabled = 139 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sleep_timeout = 140 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto double_tap_to_wake = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto autofill_service_search_uri = 150 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto skip_first_use_hints = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto unsafe_volume_music_active_ms = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_screen_show_notifications = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tv_input_hidden_inputs = 154;
+    optional SettingProto tv_input_custom_labels = 155;
+    optional SettingProto usb_audio_automatic_routing_disabled = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sleep_timeout = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto double_tap_to_wake = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // The current assistant component. It could be a voice interaction service,
     // or an activity that handles ACTION_ASSIST, or empty, which means using
     // the default handling.
-    optional SettingProto assistant = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto camera_gesture_disabled = 143 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto camera_double_tap_power_gesture_disabled = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto camera_double_twist_to_flip_enabled = 145 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto camera_lift_trigger_enabled = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_gesture_enabled = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_gesture_sensitivity = 184 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_gesture_silence_alerts_enabled = 185 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_gesture_wake_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto assist_gesture_setup_complete = 187 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_activated = 146 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_auto_mode = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_color_temperature = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_custom_start_time = 148 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_custom_end_time = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto night_display_last_activated_time = 189 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto brightness_use_twilight = 150;
-    optional SettingProto enabled_vr_listeners = 151 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto vr_display_mode = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto carrier_apps_handled = 153 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto managed_profile_contact_remote_search = 154 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto automatic_storage_manager_enabled = 155 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto automatic_storage_manager_days_to_retain = 156 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto automatic_storage_manager_bytes_cleared = 157 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto automatic_storage_manager_last_run = 158 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto automatic_storage_manager_turned_off_by_policy = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto system_navigation_keys_enabled = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto downloads_backup_enabled = 160;
-    optional SettingProto downloads_backup_allow_metered = 161;
-    optional SettingProto downloads_backup_charging_only = 162;
-    optional SettingProto automatic_storage_manager_downloads_days_to_retain = 163;
+    optional SettingProto assistant = 159 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto camera_gesture_disabled = 160 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto camera_double_tap_power_gesture_disabled = 161 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto camera_double_twist_to_flip_enabled = 162 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto camera_lift_trigger_enabled = 163 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_gesture_enabled = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_gesture_sensitivity = 165 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_gesture_silence_alerts_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_gesture_wake_enabled = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto assist_gesture_setup_complete = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_activated = 169 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_auto_mode = 170 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_color_temperature = 171 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_custom_start_time = 172 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_custom_end_time = 173 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto night_display_last_activated_time = 174 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto enabled_vr_listeners = 175 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vr_display_mode = 176 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto carrier_apps_handled = 177 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto managed_profile_contact_remote_search = 178 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto automatic_storage_manager_enabled = 179 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto automatic_storage_manager_days_to_retain = 180 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto automatic_storage_manager_bytes_cleared = 181 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto automatic_storage_manager_last_run = 182 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto automatic_storage_manager_turned_off_by_policy = 183 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto system_navigation_keys_enabled = 184 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Holds comma-separated list of ordering of QuickSettings tiles.
-    optional SettingProto qs_tiles = 164 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    reserved 165; // Removed demo_user_setup_complete
-    optional SettingProto instant_apps_enabled = 166 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto device_paired = 167 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto package_verifier_state = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto cmas_additional_broadcast_pkg = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto notification_badging = 168 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto qs_auto_added_tiles = 193 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lockdown_in_power_menu = 194 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_manager_constants = 169;
-    optional SettingProto show_first_crash_dialog_dev_option = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto bluetooth_on_while_driving = 196 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto backup_local_transport_parameters = 197;
-
+    optional SettingProto qs_tiles = 185 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto instant_apps_enabled = 186 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto device_paired = 187 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto package_verifier_state = 188 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto cmas_additional_broadcast_pkg = 189 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto notification_badging = 190 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto qs_auto_added_tiles = 191 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lockdown_in_power_menu = 192 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto backup_manager_constants = 193;
+    optional SettingProto backup_local_transport_parameters = 194;
+    optional SettingProto bluetooth_on_while_driving = 195 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Please insert fields in the same order as in
     // frameworks/base/core/java/android/provider/Settings.java.
-    // Next tag = 198
+    // Next tag = 196
 }
 
 message SystemSettingsProto {
@@ -688,29 +757,31 @@
     optional SettingProto bluetooth_discoverability_timeout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto font_scale = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto system_locales = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto display_color_mode = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screen_off_timeout = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screen_brightness = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screen_brightness_for_vr = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screen_brightness_mode = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto screen_auto_brightness_adj = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto display_color_mode = 8 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screen_off_timeout = 9 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screen_brightness = 10 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screen_brightness_for_vr = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screen_brightness_mode = 12 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto screen_auto_brightness_adj = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Determines which streams are affected by ringer mode changes. The stream
     // type's bit will be set to 1 if it should be muted when going into an
     // inaudible ringer mode.
-    optional SettingProto mode_ringer_streams_affected = 13 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto mute_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto vibrate_on = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto vibrate_input_devices = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_ring = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_system = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_voice = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_music = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_alarm = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_notification = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_bluetooth_sco = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_accessibility = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto volume_master = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto master_mono = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mode_ringer_streams_affected = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto mute_streams_affected = 15 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vibrate_on = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vibrate_input_devices = 17 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto notification_vibration_intensity = 18 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto haptic_feedback_intensity = 19 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_ring = 20 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_system = 21 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_voice = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_music = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_alarm = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_notification = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_bluetooth_sco = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_accessibility = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto volume_master = 28 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto master_mono = 29 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Whether silent mode should allow vibration feedback. This is used
     // internally in AudioService and the Sound settings activity to coordinate
     // decoupling of vibrate and silent modes. This setting will likely be
@@ -719,59 +790,63 @@
     // Not used anymore. On devices with vibrator, the user explicitly selects
     // silent or vibrate mode. Kept for use by legacy database upgrade code in
     // DatabaseHelper.
-    optional SettingProto vibrate_in_silent = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vibrate_in_silent = 30 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Appended to various volume related settings to record the previous values
     // before the settings were affected by a silent/vibrate ringer mode change.
-    optional SettingProto append_for_last_audible = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto ringtone = 28;
-    optional SettingProto ringtone_cache = 29;
-    optional SettingProto notification_sound = 30;
-    optional SettingProto notification_sound_cache = 31;
-    optional SettingProto alarm_alert = 32;
-    optional SettingProto alarm_alert_cache = 33;
-    optional SettingProto media_button_receiver = 34;
-    optional SettingProto text_auto_replace = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto text_auto_caps = 36 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto text_auto_punctuate = 37 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto text_show_password = 38 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_gtalk_service_status = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto time_12_24 = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto date_format = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto setup_wizard_has_run = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto accelerometer_rotation = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto user_rotation = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hide_rotation_lock_toggle_for_accessibility = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto vibrate_when_ringing = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dtmf_tone_when_dialing = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto dtmf_tone_type_when_dialing = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto hearing_aid = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto tty_mode = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sound_effects_enabled = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto haptic_feedback_enabled = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto notification_light_pulse = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto append_for_last_audible = 31 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto ringtone = 32;
+    optional SettingProto ringtone_cache = 33;
+    optional SettingProto notification_sound = 34;
+    optional SettingProto notification_sound_cache = 35;
+    optional SettingProto alarm_alert = 36;
+    optional SettingProto alarm_alert_cache = 37;
+    optional SettingProto media_button_receiver = 38;
+    optional SettingProto text_auto_replace = 39 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto text_auto_caps = 40 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto text_auto_punctuate = 41 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto text_show_password = 42 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_gtalk_service_status = 43 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto time_12_24 = 44 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto date_format = 45 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto setup_wizard_has_run = 46 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto accelerometer_rotation = 47 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto user_rotation = 48 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hide_rotation_lock_toggle_for_accessibility = 49 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto vibrate_when_ringing = 50 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dtmf_tone_when_dialing = 51 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto dtmf_tone_type_when_dialing = 52 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto hearing_aid = 53 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto tty_mode = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    // User-selected RTT mode. When on, outgoing and incoming calls will be
+    // answered as RTT calls when supported by the device and carrier. Boolean
+    // value.
+    optional SettingProto rtt_calling_mode = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sound_effects_enabled = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto haptic_feedback_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto notification_light_pulse = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Show pointer location on screen? 0 = no, 1 = yes.
-    optional SettingProto pointer_location = 54 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_touches = 55 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pointer_location = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_touches = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // Log raw orientation data from {@link
     // com.android.server.policy.WindowOrientationListener} for use with the
     // orientationplot.py tool.
     // 0 = no, 1 = yes
-    optional SettingProto window_orientation_listener_log = 56 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lockscreen_sounds_enabled = 57 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lockscreen_disabled = 58 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sip_receive_calls = 59 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sip_call_options = 60 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sip_always = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto sip_address_only = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto pointer_speed = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto lock_to_app_enabled = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto egg_mode = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto show_battery_percent = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    optional SettingProto when_to_make_wifi_calls = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto window_orientation_listener_log = 61 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lockscreen_sounds_enabled = 62 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lockscreen_disabled = 63 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sip_receive_calls = 64 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sip_call_options = 65 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sip_always = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto sip_address_only = 67 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto pointer_speed = 68 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto lock_to_app_enabled = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto egg_mode = 70 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_battery_percent = 71 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto when_to_make_wifi_calls = 72 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     // Please insert fields in the same order as in
     // frameworks/base/core/java/android/provider/Settings.java.
-    // Next tag = 70;
+    // Next tag = 73;
 }
 
 message SettingProto {
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index 64aa98b..c58de56 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -198,7 +198,7 @@
     }
 
     optional .android.os.WakeLockLevelEnum lock_level = 1;
-    optional string tag = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
+    optional string tag = 2;
     optional WakeLockFlagsProto flags = 3;
     optional bool is_disabled = 4;
     // Acquire time in ms
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f521e4b..9b11a33 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2552,6 +2552,12 @@
     <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
         android:protectionLevel="signature|installer" />
 
+    <!-- Allows an application to update the user app op modes.
+         Not for use by third party apps.
+         @hide -->
+    <permission android:name="android.permission.MANAGE_APP_OPS_MODES"
+        android:protectionLevel="signature|installer|verifier" />
+
     <!-- @SystemApi Allows an application to open windows that are for use by parts
          of the system user interface.
          <p>Not for use by third-party applications.
@@ -3089,7 +3095,8 @@
     <!-- Allows an application to collect usage infomation about brightness slider changes.
          <p>Not for use by third-party applications.</p>
          @hide
-         @SystemApi -->
+         @SystemApi
+         @TestApi -->
     <permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE"
         android:protectionLevel="signature|privileged|development" />
 
@@ -3102,7 +3109,8 @@
 
     <!-- Allows an application to modify the display brightness configuration
          @hide
-         @SystemApi -->
+         @SystemApi
+         @TestApi -->
     <permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"
         android:protectionLevel="signature|privileged|development" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dc937e6..6c0be1b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -148,16 +148,16 @@
     <string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
 
     <!-- Notification title to tell the user that data service is blocked by access control. -->
-    <string name="RestrictedOnDataTitle">No data service</string>
+    <string name="RestrictedOnDataTitle">No mobile data service</string>
     <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
-    <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
+    <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
     <!-- Notification title to tell the user that normal service is blocked by access control. -->
     <string name="RestrictedOnNormalTitle">No voice service</string>
     <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
-    <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
+    <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
 
     <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
-    <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
+    <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
 
     <!-- Displayed to tell the user that they should switch their network preference. -->
     <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
@@ -352,9 +352,6 @@
     <!-- Work profile deleted notification--> <skip />
     <!-- Shows up in the notification's title when the system deletes the work profile. [CHAR LIMIT=NONE] -->
     <string name="work_profile_deleted">Work profile deleted</string>
-    <!-- Content text for a notification. The Title of the notification is "Work profile deleted".
-        This says that the profile is deleted by the system as a result of the current profile owner gone missing. [CHAR LIMIT=100]-->
-    <string name="work_profile_deleted_description">Work profile deleted due to missing admin app</string>
     <!-- Content text for an expanded notification. The Title of the notification is "Work profile deleted".
         This further explains that the profile is deleted by the system as a result of the current profile admin gone missing. [CHAR LIMIT=NONE]-->
     <string name="work_profile_deleted_details">The work profile admin app is either missing or corrupted.
@@ -2447,6 +2444,18 @@
     <string name="more_item_label">More</string>
     <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the MENU button together with the shortcut to invoke the item. For example, if the shortcut to open a new tab in browser is MENU and B together, then this would be prepended to the letter "B" -->
     <string name="prepend_shortcut_label">Menu+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the META key together with the shortcut to invoke the item. -->
+    <string name="menu_meta_shortcut_label">Meta+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the CTRL key together with the shortcut to invoke the item. -->
+    <string name="menu_ctrl_shortcut_label">Ctrl+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the ALT key together with the shortcut to invoke the item. -->
+    <string name="menu_alt_shortcut_label">Alt+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SHIFT key together with the shortcut to invoke the item. -->
+    <string name="menu_shift_shortcut_label">Shift+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the SYM key together with the shortcut to invoke the item. -->
+    <string name="menu_sym_shortcut_label">Sym+</string>
+    <!-- Prepended to the shortcut for a menu item to indicate that the user should hold the FUNCTION key together with the shortcut to invoke the item. -->
+    <string name="menu_function_shortcut_label">Function+</string>
     <!-- Displayed in place of the regular shortcut letter when a menu item has Menu+space for the shortcut. -->
     <string name="menu_space_shortcut_label">space</string>
     <!-- Displayed in place of the regular shortcut letter when a menu item has Menu+enter for the shortcut. -->
@@ -4880,10 +4889,16 @@
     <!-- Notification action for editing a screenshot (drawing on it, cropping it, etc) -->
     <string name="screenshot_edit">Edit</string>
 
-    <!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
+    <!-- Title for the notification channel notifying user of settings system changes. [CHAR LIMIT=NONE] -->
     <string name="notification_channel_system_changes">System changes</string>
-    <!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
-    <string name="zen_upgrade_notification_title">Do Not Disturb is hiding notifications to help you focus</string>
+    <!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_do_not_disturb">Do Not Disturb</string>
+    <!-- Title of notification indicating do not disturb visual interruption settings have changed when upgrading to P -->
+    <string name="zen_upgrade_notification_visd_title">Do Not Disturb is hiding notifications to help you focus</string>
     <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
-    <string name="zen_upgrade_notification_content">This is a new feature from the latest system update. Tap to change.</string>
+    <string name="zen_upgrade_notification_visd_content">This is new behavior. Tap to change.</string>
+    <!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
+    <string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
+    <!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
+    <string name="zen_upgrade_notification_content">Tap to check what\'s blocked.</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 97116f5..55e9157 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -528,9 +528,15 @@
   <java-symbol type="string" name="delete" />
   <java-symbol type="string" name="deleteText" />
   <java-symbol type="string" name="grant_permissions_header_text" />
+  <java-symbol type="string" name="menu_alt_shortcut_label" />
+  <java-symbol type="string" name="menu_ctrl_shortcut_label" />
   <java-symbol type="string" name="menu_delete_shortcut_label" />
   <java-symbol type="string" name="menu_enter_shortcut_label" />
+  <java-symbol type="string" name="menu_function_shortcut_label" />
+  <java-symbol type="string" name="menu_meta_shortcut_label" />
   <java-symbol type="string" name="menu_space_shortcut_label" />
+  <java-symbol type="string" name="menu_shift_shortcut_label" />
+  <java-symbol type="string" name="menu_sym_shortcut_label" />
   <java-symbol type="string" name="notification_title" />
   <java-symbol type="string" name="permission_request_notification_with_subtitle" />
   <java-symbol type="string" name="prepend_shortcut_label" />
@@ -3123,6 +3129,7 @@
   <java-symbol type="string" name="notification_channel_usb" />
   <java-symbol type="string" name="notification_channel_heavy_weight_app" />
   <java-symbol type="string" name="notification_channel_system_changes" />
+  <java-symbol type="string" name="notification_channel_do_not_disturb" />
   <java-symbol type="string" name="config_defaultAutofillService" />
   <java-symbol type="string" name="config_defaultTextClassifierPackage" />
 
@@ -3289,6 +3296,8 @@
 
   <java-symbol type="string" name="zen_upgrade_notification_title" />
   <java-symbol type="string" name="zen_upgrade_notification_content" />
+  <java-symbol type="string" name="zen_upgrade_notification_visd_title" />
+  <java-symbol type="string" name="zen_upgrade_notification_visd_content" />
 
   <java-symbol type="string" name="config_managed_provisioning_package" />
 
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 970a0f0..7b5ad9a 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -14,15 +14,16 @@
      limitations under the License.
 -->
 <configuration description="Runs Frameworks Core Tests.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="FrameworksCoreTests.apk" />
         <option name="test-file-name" value="BstatsTestApp.apk" />
     </target_preparer>
-
-    <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="FrameworksCoreTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.coretests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index fd1027c..be0372d 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -67,6 +67,7 @@
   <hidden-api-whitelisted-app package="com.android.pacprocessor" />
   <hidden-api-whitelisted-app package="com.android.phone" />
   <hidden-api-whitelisted-app package="com.android.pmc" />
+  <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
   <hidden-api-whitelisted-app package="com.android.printspooler" />
   <hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
   <hidden-api-whitelisted-app package="com.android.providers.contacts" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f27c11d..20c22b7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -167,10 +167,8 @@
         nativeSetDefault(t.native_instance);
     }
 
-    // TODO: Make this public API. (b/64852739)
-    /** @hide */
-    @VisibleForTesting
-    public int getWeight() {
+    /** Returns the typeface's weight value */
+    public @IntRange(from = 0, to = 1000) int getWeight() {
         return mWeight;
     }
 
@@ -883,6 +881,15 @@
     }
 
     /**
+     * This method is used by supportlib-v27.
+     * TODO: Remove private API use in supportlib: http://b/72665240
+     */
+    private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
+                int italic) {
+        return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
+    }
+
+    /**
      * Create a new typeface from an array of font families, including
      * also the font families in the fallback list.
      * @param fallbackName the family name. If given families don't support characters, the
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index e60c5f9..91bface 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -182,16 +182,6 @@
     public static final int COMMAND_CODE_PLAYBACK_ADJUST_VOLUME = 11;
 
     /**
-     * Command code for {@link MediaController2#setPlaylistParams(PlaylistParams)}.
-     * <p>
-     * Command would be sent directly to the player if the session doesn't reject the request
-     * through the {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}.
-     * @hide
-     */
-    // TODO(jaewan): Remove (b/74116823)
-    public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 12;
-
-    /**
      * Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}.
      * <p>
      * Command would be sent directly to the playlist agent if the session doesn't reject the
@@ -314,6 +304,13 @@
     public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 27;
 
     /**
+     * Command code for {@link MediaController2#setRating(String, Rating2)}.
+     * @hide
+     */
+    // TODO(jaewan): Unhide
+    public static final int COMMAND_CODE_SET_RATING = 29;
+
+    /**
      * Command code for {@link MediaBrowser2} specific functions that allows navigation and search
      * from the {@link MediaLibraryService2}. This would be ignored for a {@link MediaSession2},
      * not {@link android.media.MediaLibraryService2.MediaLibrarySession}.
@@ -325,11 +322,6 @@
     /**
      * @hide
      */
-    public static final int COMMAND_CODE_MAX = 28;
-
-    /**
-     * @hide
-     */
     @IntDef({ERROR_CODE_UNKNOWN_ERROR, ERROR_CODE_APP_ERROR, ERROR_CODE_NOT_SUPPORTED,
             ERROR_CODE_AUTHENTICATION_EXPIRED, ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
             ERROR_CODE_CONCURRENT_STREAM_LIMIT, ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
@@ -452,6 +444,13 @@
                     .createMediaSession2Command(this, COMMAND_CODE_CUSTOM, action, extras);
         }
 
+        /**
+         * @hide
+         */
+        public CommandProvider getProvider() {
+            return mProvider;
+        }
+
         public int getCommandCode() {
             return mProvider.getCommandCode_impl();
         }
@@ -510,6 +509,13 @@
                     .createMediaSession2CommandGroup(context, this, others);
         }
 
+        /**
+         * @hide
+         */
+        public CommandGroup(@NonNull CommandGroupProvider provider) {
+            mProvider = provider;
+        }
+
         public void addCommand(@NonNull Command command) {
             mProvider.addCommand_impl(command);
         }
@@ -622,7 +628,6 @@
          * @see #COMMAND_CODE_PLAYBACK_REWIND
          * @see #COMMAND_CODE_PLAYBACK_SEEK_TO
          * @see #COMMAND_CODE_PLAYLIST_SKIP_TO_PLAYLIST_ITEM
-         * @see #COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS
          * @see #COMMAND_CODE_PLAYLIST_ADD_ITEM
          * @see #COMMAND_CODE_PLAYLIST_REMOVE_ITEM
          * @see #COMMAND_CODE_PLAYLIST_GET_LIST
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 2482095..085e112 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -563,8 +563,7 @@
 
             // If there were no scan results, create an AP for the currently connected network (if
             // it exists).
-            // TODO(sghuman): Investigate if this works for an ephemeral (auto-connected) network
-            // when there are no scan results, as it may not have a valid WifiConfiguration
+            // TODO(b/b/73076869): Add support for passpoint (ephemeral) networks
             if (accessPoints.isEmpty() && connectionConfig != null) {
                 AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);
                 activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 54c02a2..e435a72 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -18,9 +18,11 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -50,6 +52,7 @@
 import android.text.style.TtsSpan;
 
 import com.android.settingslib.R;
+import com.android.settingslib.utils.ThreadUtils;
 import com.android.settingslib.wifi.AccessPoint.Speed;
 
 import org.junit.Before;
@@ -61,6 +64,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -79,6 +83,8 @@
     private Context mContext;
     @Mock private RssiCurve mockBadgeCurve;
     @Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
+    public static final int NETWORK_ID = 123;
+    public static final int DEFAULT_RSSI = -55;
 
     private static ScanResult createScanResult(String ssid, String bssid, int rssi) {
         ScanResult scanResult = new ScanResult();
@@ -753,16 +759,15 @@
         assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
     }
     @Test
-    public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
-        int networkId = 123;
-        int rssi = -55;
+    public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener()
+            throws InterruptedException {
         WifiConfiguration config = new WifiConfiguration();
-        config.networkId = networkId;
+        config.networkId = NETWORK_ID;
         config.numNoInternetAccessReports = 1;
 
         WifiInfo wifiInfo = new WifiInfo();
-        wifiInfo.setNetworkId(networkId);
-        wifiInfo.setRssi(rssi);
+        wifiInfo.setNetworkId(NETWORK_ID);
+        wifiInfo.setRssi(DEFAULT_RSSI);
 
         NetworkInfo networkInfo =
                 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -770,8 +775,8 @@
 
         AccessPoint ap = new TestAccessPointBuilder(mContext)
                 .setNetworkInfo(networkInfo)
-                .setNetworkId(networkId)
-                .setRssi(rssi)
+                .setNetworkId(NETWORK_ID)
+                .setRssi(DEFAULT_RSSI)
                 .setWifiInfo(wifiInfo)
                 .build();
 
@@ -781,18 +786,131 @@
         config.validatedInternetAccess = true;
 
         assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse();
+
+        // Wait for MainHandler to process callback
+        CountDownLatch latch = new CountDownLatch(1);
+        ThreadUtils.postOnMainThread(latch::countDown);
+
+        latch.await();
         verify(mockListener).onAccessPointChanged(ap);
     }
 
     @Test
-    public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
-        int networkId = 123;
-        int rssi = -55;
+    public void testConnectionInfo_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+            throws InterruptedException {
         WifiConfiguration config = new WifiConfiguration();
-        config.networkId = networkId;
+        config.networkId = NETWORK_ID;
+        config.numNoInternetAccessReports = 1;
+
         WifiInfo wifiInfo = new WifiInfo();
-        wifiInfo.setNetworkId(networkId);
-        wifiInfo.setRssi(rssi);
+        wifiInfo.setNetworkId(NETWORK_ID);
+        wifiInfo.setRssi(DEFAULT_RSSI);
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+        AccessPoint ap = new TestAccessPointBuilder(mContext)
+                .setNetworkInfo(networkInfo)
+                .setNetworkId(NETWORK_ID)
+                .setRssi(DEFAULT_RSSI)
+                .setWifiInfo(wifiInfo)
+                .build();
+
+        WifiConfiguration newConfig = new WifiConfiguration(config);
+        config.validatedInternetAccess = true;
+
+        performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+                ap, () -> assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse());
+
+    }
+
+    private void performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+            AccessPoint ap, Runnable r) {
+        AccessPoint.AccessPointListener mockListener = mock(AccessPoint.AccessPointListener.class);
+        ap.setListener(mockListener);
+
+        // Put a latch on the MainHandler to prevent the callback from being invoked instantly
+        CountDownLatch latch1 = new CountDownLatch(1);
+        ThreadUtils.postOnMainThread(() -> {
+            try{
+                latch1.await();
+            } catch (InterruptedException e) {
+                fail("Interruped Exception thrown while awaiting latch countdown");
+            }
+        });
+
+        r.run();
+
+        ap.setListener(null);
+        latch1.countDown();
+
+        // The second latch ensures the previously posted listener invocation has processed on the
+        // main thread.
+        CountDownLatch latch2 = new CountDownLatch(1);
+        ThreadUtils.postOnMainThread(latch2::countDown);
+
+        try{
+            latch2.await();
+        } catch (InterruptedException e) {
+            fail("Interruped Exception thrown while awaiting latch countdown");
+        }
+    }
+
+    @Test
+    public void testUpdateScanResults_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+            throws InterruptedException {
+        String ssid = "ssid";
+        int newRssi = -80;
+        AccessPoint ap = new TestAccessPointBuilder(mContext).setSsid(ssid).build();
+
+        ScanResult scanResult = new ScanResult();
+        scanResult.SSID = ssid;
+        scanResult.level = newRssi;
+        scanResult.BSSID = "bssid";
+        scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
+        scanResult.capabilities = "";
+
+        performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+                ap, () -> ap.setScanResults(Collections.singletonList(scanResult)));
+    }
+
+    @Test
+    public void testUpdateConfig_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+            throws InterruptedException {
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = NETWORK_ID;
+        config.numNoInternetAccessReports = 1;
+
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setNetworkId(NETWORK_ID);
+        wifiInfo.setRssi(DEFAULT_RSSI);
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+        AccessPoint ap = new TestAccessPointBuilder(mContext)
+                .setNetworkInfo(networkInfo)
+                .setNetworkId(NETWORK_ID)
+                .setRssi(DEFAULT_RSSI)
+                .setWifiInfo(wifiInfo)
+                .build();
+
+        WifiConfiguration newConfig = new WifiConfiguration(config);
+        config.validatedInternetAccess = true;
+
+        performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+                ap, () -> ap.update(newConfig));
+    }
+
+    @Test
+    public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = NETWORK_ID;
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setNetworkId(NETWORK_ID);
+        wifiInfo.setRssi(DEFAULT_RSSI);
 
         NetworkInfo networkInfo =
                 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -800,8 +918,8 @@
 
         AccessPoint ap = new TestAccessPointBuilder(mContext)
                 .setNetworkInfo(networkInfo)
-                .setNetworkId(networkId)
-                .setRssi(rssi)
+                .setNetworkId(NETWORK_ID)
+                .setRssi(DEFAULT_RSSI)
                 .setWifiInfo(wifiInfo)
                 .build();
 
@@ -847,34 +965,34 @@
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
 
         ap.update(
-        mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
+            mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(speed1);
     }
 
     @Test
     public void testSpeedLabelFallbackScoreIgnoresNullCurves() {
-        int rssi = -55;
         String bssid = "00:00:00:00:00:00";
-        int networkId = 123;
 
         WifiInfo info = new WifiInfo();
-        info.setRssi(rssi);
+        info.setRssi(DEFAULT_RSSI);
         info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
         info.setBSSID(bssid);
-        info.setNetworkId(networkId);
+        info.setNetworkId(NETWORK_ID);
 
         ArrayList<ScanResult> scanResults = new ArrayList<>();
-        ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi);
+        ScanResult scanResultUnconnected =
+                createScanResult(TEST_SSID, "11:11:11:11:11:11", DEFAULT_RSSI);
         scanResults.add(scanResultUnconnected);
 
-        ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi);
+        ScanResult scanResultConnected =
+                createScanResult(TEST_SSID, bssid, DEFAULT_RSSI);
         scanResults.add(scanResultConnected);
 
         AccessPoint ap =
                 new TestAccessPointBuilder(mContext)
                         .setActive(true)
-                        .setNetworkId(networkId)
+                        .setNetworkId(NETWORK_ID)
                         .setSsid(TEST_SSID)
                         .setScanResults(scanResults)
                         .setWifiInfo(info)
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index ca965f3..7fb4dc5 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -721,7 +721,7 @@
         // mStaleAccessPoints is true
         verify(mockWifiListenerExecutor, never()).onAccessPointsChanged();
 
-        assertThat(tracker.getAccessPoints().size()).isEqualTo(1);
+        assertThat(tracker.getAccessPoints()).hasSize(1);
         assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index cfcfb95..4530f80 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -40,6 +40,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -2594,15 +2595,26 @@
             loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0);
 
             // Set the preferred network mode to target desired value or Default
-            // value defined in RILConstants
-            int type;
-            type = RILConstants.PREFERRED_NETWORK_MODE;
-            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
+            // value defined in system property
+            String val = "";
+            String mode;
+            for (int phoneId = 0;
+                    phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
+                mode = TelephonyManager.getTelephonyProperty(phoneId,
+                        "ro.telephony.default_network",
+                        Integer.toString(RILConstants.PREFERRED_NETWORK_MODE));
+                if (phoneId == 0) {
+                    val = mode;
+                } else {
+                    val = val + "," + mode;
+                }
+            }
+            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val);
 
             // Set the preferred cdma subscription source to target desired value or default
             // value defined in Phone
-            type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
-                        Phone.PREFERRED_CDMA_SUBSCRIPTION);
+            int type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
+                    Phone.PREFERRED_CDMA_SUBSCRIPTION);
             loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type);
 
             loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index ccb4d8c..53cff4e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -39,19 +39,15 @@
         SettingsState globalSettings = settingsRegistry.getSettingsLocked(
                 SettingsProvider.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
         if (globalSettings != null) {
-            long globalSettingsToken = proto.start(SettingsServiceDumpProto.GLOBAL_SETTINGS);
-            dumpProtoGlobalSettingsLocked(globalSettings, proto);
-            proto.end(globalSettingsToken);
+            dumpProtoGlobalSettingsLocked(proto, SettingsServiceDumpProto.GLOBAL_SETTINGS, globalSettings);
         }
 
         // Per-user settings
         SparseBooleanArray users = settingsRegistry.getKnownUsersLocked();
         final int userCount = users.size();
         for (int i = 0; i < userCount; i++) {
-            long userSettingsToken = proto.start(SettingsServiceDumpProto.USER_SETTINGS);
-            dumpProtoUserSettingsLocked(
-                    settingsRegistry, UserHandle.of(users.keyAt(i)), proto);
-            proto.end(userSettingsToken);
+            dumpProtoUserSettingsLocked(proto, SettingsServiceDumpProto.USER_SETTINGS,
+                    settingsRegistry, UserHandle.of(users.keyAt(i)));
         }
     }
 
@@ -63,30 +59,33 @@
      * @param proto The proto buf stream to dump to
      */
     private static void dumpProtoUserSettingsLocked(
+            @NonNull ProtoOutputStream proto,
+            long fieldId,
             SettingsProvider.SettingsRegistry settingsRegistry,
-            @NonNull UserHandle user,
-            @NonNull ProtoOutputStream proto) {
+            @NonNull UserHandle user) {
+        final long token = proto.start(fieldId);
+
         proto.write(UserSettingsProto.USER_ID, user.getIdentifier());
 
         SettingsState secureSettings = settingsRegistry.getSettingsLocked(
                 SettingsProvider.SETTINGS_TYPE_SECURE, user.getIdentifier());
         if (secureSettings != null) {
-            long secureSettingsToken = proto.start(UserSettingsProto.SECURE_SETTINGS);
-            dumpProtoSecureSettingsLocked(secureSettings, proto);
-            proto.end(secureSettingsToken);
+            dumpProtoSecureSettingsLocked(proto, UserSettingsProto.SECURE_SETTINGS, secureSettings);
         }
 
         SettingsState systemSettings = settingsRegistry.getSettingsLocked(
                 SettingsProvider.SETTINGS_TYPE_SYSTEM, user.getIdentifier());
         if (systemSettings != null) {
-            long systemSettingsToken = proto.start(UserSettingsProto.SYSTEM_SETTINGS);
-            dumpProtoSystemSettingsLocked(systemSettings, proto);
-            proto.end(systemSettingsToken);
+            dumpProtoSystemSettingsLocked(proto, UserSettingsProto.SYSTEM_SETTINGS, systemSettings);
         }
+
+        proto.end(token);
     }
 
     private static void dumpProtoGlobalSettingsLocked(
-            @NonNull SettingsState s, @NonNull ProtoOutputStream p) {
+            @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) {
+        final long token = p.start(fieldId);
+
         s.dumpHistoricalOperations(p, GlobalSettingsProto.HISTORICAL_OPERATIONS);
 
         // This uses the same order as in Settings.Global.
@@ -102,6 +101,11 @@
         dumpSetting(s, p,
                 Settings.Global.THEATER_MODE_ON,
                 GlobalSettingsProto.THEATER_MODE_ON);
+        // RADIO_BLUETOOTH is just a constant and not an actual setting.
+        // RADIO_WIFI is just a constant and not an actual setting.
+        // RADIO_WIMAX is just a constant and not an actual setting.
+        // RADIO_CELL is just a constant and not an actual setting.
+        // RADIO_NFC is just a constant and not an actual setting.
         dumpSetting(s, p,
                 Settings.Global.AIRPLANE_MODE_RADIOS,
                 GlobalSettingsProto.AIRPLANE_MODE_RADIOS);
@@ -253,6 +257,9 @@
                 Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                 GlobalSettingsProto.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED);
         dumpSetting(s, p,
+                Settings.Global.PRIV_APP_OOB_ENABLED,
+                GlobalSettingsProto.PRIV_APP_OOB_ENABLED);
+        dumpSetting(s, p,
                 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
                 GlobalSettingsProto.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS);
         dumpSetting(s, p,
@@ -343,6 +350,9 @@
                 Settings.Global.NETWORK_SCORER_APP,
                 GlobalSettingsProto.NETWORK_SCORER_APP);
         dumpSetting(s, p,
+                Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE,
+                GlobalSettingsProto.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE);
+        dumpSetting(s, p,
                 Settings.Global.NITZ_UPDATE_DIFF,
                 GlobalSettingsProto.NITZ_UPDATE_DIFF);
         dumpSetting(s, p,
@@ -499,6 +509,9 @@
                 Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                 GlobalSettingsProto.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
         dumpSetting(s, p,
+                Settings.Global.WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                GlobalSettingsProto.WIFI_CARRIER_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+        dumpSetting(s, p,
                 Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
                 GlobalSettingsProto.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
         dumpSetting(s, p,
@@ -523,6 +536,9 @@
                 Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
                 GlobalSettingsProto.WIFI_SCAN_ALWAYS_AVAILABLE);
         dumpSetting(s, p,
+                Settings.Global.SOFT_AP_TIMEOUT_ENABLED,
+                GlobalSettingsProto.SOFT_AP_TIMEOUT_ENABLED);
+        dumpSetting(s, p,
                 Settings.Global.WIFI_WAKEUP_ENABLED,
                 GlobalSettingsProto.WIFI_WAKEUP_ENABLED);
         dumpSetting(s, p,
@@ -532,6 +548,9 @@
                 Settings.Global.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS,
                 GlobalSettingsProto.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS);
         dumpSetting(s, p,
+                Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
+                GlobalSettingsProto.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS);
+        dumpSetting(s, p,
                 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
                 GlobalSettingsProto.NETWORK_RECOMMENDATIONS_ENABLED);
         dumpSetting(s, p,
@@ -544,12 +563,27 @@
                 Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS,
                 GlobalSettingsProto.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
         dumpSetting(s, p,
-                Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
-                GlobalSettingsProto.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS);
-        dumpSetting(s, p,
                 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
                 GlobalSettingsProto.BLE_SCAN_ALWAYS_AVAILABLE);
         dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_LOW_POWER_WINDOW_MS,
+                GlobalSettingsProto.BLE_SCAN_LOW_POWER_WINDOW_MS);
+        dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_BALANCED_WINDOW_MS,
+                GlobalSettingsProto.BLE_SCAN_BALANCED_WINDOW_MS);
+        dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
+                GlobalSettingsProto.BLE_SCAN_LOW_LATENCY_WINDOW_MS);
+        dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_LOW_POWER_INTERVAL_MS,
+                GlobalSettingsProto.BLE_SCAN_LOW_POWER_INTERVAL_MS);
+        dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_BALANCED_INTERVAL_MS,
+                GlobalSettingsProto.BLE_SCAN_BALANCED_INTERVAL_MS);
+        dumpSetting(s, p,
+                Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
+                GlobalSettingsProto.BLE_SCAN_LOW_LATENCY_INTERVAL_MS);
+        dumpSetting(s, p,
                 Settings.Global.WIFI_SAVED_STATE,
                 GlobalSettingsProto.WIFI_SAVED_STATE);
         dumpSetting(s, p,
@@ -645,12 +679,12 @@
         dumpSetting(s, p,
                 Settings.Global.DROPBOX_RESERVE_PERCENT,
                 GlobalSettingsProto.DROPBOX_RESERVE_PERCENT);
-        dumpSetting(s, p,
+        dumpRepeatedSetting(s, p,
                 Settings.Global.DROPBOX_TAG_PREFIX,
-                GlobalSettingsProto.DROPBOX_TAG_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.DROPBOX_SETTINGS);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.ERROR_LOGCAT_PREFIX,
-                GlobalSettingsProto.ERROR_LOGCAT_PREFIX);
+                GlobalSettingsProto.ERROR_LOGCAT_LINES);
         dumpSetting(s, p,
                 Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
                 GlobalSettingsProto.SYS_FREE_STORAGE_LOG_INTERVAL);
@@ -756,42 +790,42 @@
         dumpSetting(s, p,
                 Settings.Global.PRIVATE_DNS_SPECIFIER,
                 GlobalSettingsProto.PRIVATE_DNS_SPECIFIER);
-        dumpSetting(s, p,
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_HEADSET_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_HEADSET_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_A2DP_SINK_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_A2DP_SRC_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_A2DP_OPTIONAL_CODECS_ENABLED);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_INPUT_DEVICE_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_MAP_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_MAP_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_MAP_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_MAP_CLIENT_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_PBAP_CLIENT_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_SAP_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_SAP_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_SAP_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_PAN_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_PAN_PRIORITY_PREFIX);
-        dumpSetting(s, p,
+                GlobalSettingsProto.BLUETOOTH_PAN_PRIORITIES);
+        dumpRepeatedSetting(s, p,
                 Settings.Global.BLUETOOTH_HEARING_AID_PRIORITY_PREFIX,
-                GlobalSettingsProto.BLUETOOTH_HEARING_AID_PRIORITY_PREFIX);
+                GlobalSettingsProto.BLUETOOTH_HEARING_AID_PRIORITIES);
         dumpSetting(s, p,
                 Settings.Global.ACTIVITY_MANAGER_CONSTANTS,
                 GlobalSettingsProto.ACTIVITY_MANAGER_CONSTANTS);
@@ -802,12 +836,36 @@
                 Settings.Global.BATTERY_SAVER_CONSTANTS,
                 GlobalSettingsProto.BATTERY_SAVER_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
+                GlobalSettingsProto.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS);
+        dumpSetting(s, p,
+                Settings.Global.BATTERY_TIP_CONSTANTS,
+                GlobalSettingsProto.BATTERY_TIP_CONSTANTS);
+        dumpSetting(s, p,
                 Settings.Global.ANOMALY_DETECTION_CONSTANTS,
                 GlobalSettingsProto.ANOMALY_DETECTION_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Global.ANOMALY_CONFIG_VERSION,
+                GlobalSettingsProto.ANOMALY_CONFIG_VERSION);
+        dumpSetting(s, p,
+                Settings.Global.ANOMALY_CONFIG,
+                GlobalSettingsProto.ANOMALY_CONFIG);
+        dumpSetting(s, p,
                 Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS,
                 GlobalSettingsProto.ALWAYS_ON_DISPLAY_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Global.SYS_VDSO,
+                GlobalSettingsProto.SYS_VDSO);
+        dumpSetting(s, p,
+                Settings.Global.SYS_UIDCPUPOWER,
+                GlobalSettingsProto.SYS_UIDCPUPOWER);
+        dumpSetting(s, p,
+                Settings.Global.FPS_DEVISOR,
+                GlobalSettingsProto.FPS_DIVISOR);
+        dumpSetting(s, p,
+                Settings.Global.DISPLAY_PANEL_LPM,
+                GlobalSettingsProto.DISPLAY_PANEL_LPM);
+        dumpSetting(s, p,
                 Settings.Global.APP_IDLE_CONSTANTS,
                 GlobalSettingsProto.APP_IDLE_CONSTANTS);
         dumpSetting(s, p,
@@ -829,6 +887,42 @@
                 Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
                 GlobalSettingsProto.TEXT_CLASSIFIER_CONSTANTS);
         dumpSetting(s, p,
+                Settings.Global.BATTERY_STATS_CONSTANTS,
+                GlobalSettingsProto.BATTERY_STATS_CONSTANTS);
+        dumpSetting(s, p,
+                Settings.Global.SYNC_MANAGER_CONSTANTS,
+                GlobalSettingsProto.SYNC_MANAGER_CONSTANTS);
+        dumpSetting(s, p,
+                Settings.Global.APP_STANDBY_ENABLED,
+                GlobalSettingsProto.APP_STANDBY_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
+                GlobalSettingsProto.APP_AUTO_RESTRICTION_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.FORCED_APP_STANDBY_ENABLED,
+                GlobalSettingsProto.FORCED_APP_STANDBY_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
+                GlobalSettingsProto.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.OFF_BODY_RADIOS_OFF_FOR_SMALL_BATTERY_ENABLED,
+                GlobalSettingsProto.OFF_BODY_RADIOS_OFF_FOR_SMALL_BATTERY_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.OFF_BODY_RADIOS_OFF_DELAY_MS,
+                GlobalSettingsProto.OFF_BODY_RADIOS_OFF_DELAY_MS);
+        dumpSetting(s, p,
+                Settings.Global.WIFI_ON_WHEN_PROXY_DISCONNECTED,
+                GlobalSettingsProto.WIFI_ON_WHEN_PROXY_DISCONNECTED);
+        dumpSetting(s, p,
+                Settings.Global.TIME_ONLY_MODE_ENABLED,
+                GlobalSettingsProto.TIME_ONLY_MODE_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.NETWORK_WATCHLIST_ENABLED,
+                GlobalSettingsProto.NETWORK_WATCHLIST_ENABLED);
+        dumpSetting(s, p,
+                Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
+                GlobalSettingsProto.KEEP_PROFILE_IN_BACKGROUND);
+        dumpSetting(s, p,
                 Settings.Global.WINDOW_ANIMATION_SCALE,
                 GlobalSettingsProto.WINDOW_ANIMATION_SCALE);
         dumpSetting(s, p,
@@ -870,15 +964,6 @@
         dumpSetting(s, p,
                 Settings.Global.GPU_DEBUG_LAYERS,
                 GlobalSettingsProto.GPU_DEBUG_LAYERS);
-        dumpSetting(s, p,
-                Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
-                GlobalSettingsProto.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING);
-        dumpSetting(s, p,
-                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
-                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT);
-        dumpSetting(s, p,
-                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
-                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS);
         // Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Global.LOW_POWER_MODE,
@@ -887,6 +972,9 @@
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL,
                 GlobalSettingsProto.LOW_POWER_MODE_TRIGGER_LEVEL);
         dumpSetting(s, p,
+                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
+                GlobalSettingsProto.LOW_POWER_MODE_TRIGGER_LEVEL_MAX);
+        dumpSetting(s, p,
                 Settings.Global.ALWAYS_FINISH_ACTIVITIES,
                 GlobalSettingsProto.ALWAYS_FINISH_ACTIVITIES);
         dumpSetting(s, p,
@@ -962,6 +1050,9 @@
                 Settings.Global.POLICY_CONTROL,
                 GlobalSettingsProto.POLICY_CONTROL);
         dumpSetting(s, p,
+                Settings.Global.EMULATE_DISPLAY_CUTOUT,
+                GlobalSettingsProto.EMULATE_DISPLAY_CUTOUT);
+        dumpSetting(s, p,
                 Settings.Global.ZEN_MODE,
                 GlobalSettingsProto.ZEN_MODE);
         dumpSetting(s, p,
@@ -971,6 +1062,9 @@
                 Settings.Global.ZEN_MODE_CONFIG_ETAG,
                 GlobalSettingsProto.ZEN_MODE_CONFIG_ETAG);
         dumpSetting(s, p,
+                Settings.Global.ZEN_DURATION,
+                GlobalSettingsProto.ZEN_DURATION);
+        dumpSetting(s, p,
                 Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
                 GlobalSettingsProto.HEADS_UP_NOTIFICATIONS_ENABLED);
         dumpSetting(s, p,
@@ -1061,9 +1155,18 @@
                 Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
                 GlobalSettingsProto.STORAGE_SETTINGS_CLOBBER_THRESHOLD);
         dumpSetting(s, p,
+                Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
+                GlobalSettingsProto.LOCATION_GLOBAL_KILL_SWITCH);
+        dumpSetting(s, p,
+                Settings.Global.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION,
+                GlobalSettingsProto.OVERRIDE_SETTINGS_PROVIDER_RESTORE_ANY_VERSION);
+        dumpSetting(s, p,
                 Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
                 GlobalSettingsProto.CHAINED_BATTERY_ATTRIBUTION_ENABLED);
         dumpSetting(s, p,
+                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES,
+                GlobalSettingsProto.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
+        dumpSetting(s, p,
                 Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
                 GlobalSettingsProto.HIDDEN_API_BLACKLIST_EXEMPTIONS);
         dumpSetting(s, p,
@@ -1121,6 +1224,18 @@
                 Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
                 GlobalSettingsProto.NOTIFICATION_SNOOZE_OPTIONS);
         dumpSetting(s, p,
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+                GlobalSettingsProto.SQLITE_COMPATIBILITY_WAL_FLAGS);
+        dumpSetting(s, p,
+                Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
+                GlobalSettingsProto.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING);
+        dumpSetting(s, p,
+                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
+                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT);
+        dumpSetting(s, p,
+                Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS,
+                GlobalSettingsProto.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS);
+        dumpSetting(s, p,
                 Settings.Global.ZRAM_ENABLED,
                 GlobalSettingsProto.ZRAM_ENABLED);
         dumpSetting(s, p,
@@ -1138,14 +1253,19 @@
         dumpSetting(s, p,
                 Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION,
                 GlobalSettingsProto.SHOW_ZEN_UPGRADE_NOTIFICATION);
-        dumpSetting(s, p,
-                Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
-                GlobalSettingsProto.APP_AUTO_RESTRICTION_ENABLED);
-        dumpSetting(s, p,
-                Settings.Global.ZEN_DURATION,
-                GlobalSettingsProto.ZEN_DURATION);
-
         // Please insert new settings using the same order as in Settings.Global.
+
+        p.end(token);
+    }
+
+    /** Dumps settings that use a common prefix into a repeated field. */
+    private static void dumpRepeatedSetting(@NonNull SettingsState settings,
+            @NonNull ProtoOutputStream proto, String settingPrefix, long fieldId) {
+        for (String s : settings.getSettingNamesLocked()) {
+            if (s.startsWith(settingPrefix)) {
+                dumpSetting(settings, proto, s, fieldId);
+            }
+        }
     }
 
     /** Dump a single {@link SettingsState.Setting} to a proto buf */
@@ -1167,7 +1287,9 @@
     }
 
     static void dumpProtoSecureSettingsLocked(
-            @NonNull SettingsState s, @NonNull ProtoOutputStream p) {
+            @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) {
+        final long token = p.start(fieldId);
+
         s.dumpHistoricalOperations(p, SecureSettingsProto.HISTORICAL_OPERATIONS);
 
         // This uses the same order as in Settings.Secure.
@@ -1199,6 +1321,24 @@
         dumpSetting(s, p,
                 Settings.Secure.AUTOFILL_SERVICE,
                 SecureSettingsProto.AUTOFILL_SERVICE);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION,
+                SecureSettingsProto.AUTOFILL_FEATURE_FIELD_CLASSIFICATION);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE,
+                SecureSettingsProto.AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE,
+                SecureSettingsProto.AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT,
+                SecureSettingsProto.AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH,
+                SecureSettingsProto.AUTOFILL_USER_DATA_MAX_VALUE_LENGTH);
+        dumpSetting(s, p,
+                Settings.Secure.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH,
+                SecureSettingsProto.AUTOFILL_USER_DATA_MIN_VALUE_LENGTH);
         // Settings.Secure.DEVICE_PROVISIONED intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Secure.USER_SETUP_COMPLETE,
@@ -1209,9 +1349,9 @@
         dumpSetting(s, p,
                 Settings.Secure.TV_USER_SETUP_COMPLETE,
                 SecureSettingsProto.TV_USER_SETUP_COMPLETE);
-        dumpSetting(s, p,
+        dumpRepeatedSetting(s, p,
                 Settings.Secure.COMPLETED_CATEGORY_PREFIX,
-                SecureSettingsProto.COMPLETED_CATEGORY_PREFIX);
+                SecureSettingsProto.COMPLETED_CATEGORIES);
         dumpSetting(s, p,
                 Settings.Secure.ENABLED_INPUT_METHODS,
                 SecureSettingsProto.ENABLED_INPUT_METHODS);
@@ -1238,6 +1378,9 @@
         dumpSetting(s, p,
                 Settings.Secure.LOCATION_MODE,
                 SecureSettingsProto.LOCATION_MODE);
+        dumpSetting(s, p,
+                Settings.Secure.LOCATION_CHANGER,
+                SecureSettingsProto.LOCATION_CHANGER);
         // Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
@@ -1309,6 +1452,9 @@
                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
                 SecureSettingsProto.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
         dumpSetting(s, p,
+                Settings.Secure.KEYGUARD_SLICE_URI,
+                SecureSettingsProto.KEYGUARD_SLICE_URI);
+        dumpSetting(s, p,
                 Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
                 SecureSettingsProto.ACCESSIBILITY_SPEAK_PASSWORD);
         dumpSetting(s, p,
@@ -1324,9 +1470,6 @@
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                 SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE);
         dumpSetting(s, p,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
-                SecureSettingsProto.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE);
-        dumpSetting(s, p,
                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                 SecureSettingsProto.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
         dumpSetting(s, p,
@@ -1618,6 +1761,12 @@
                 Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
                 SecureSettingsProto.ASSIST_DISCLOSURE_ENABLED);
         dumpSetting(s, p,
+                Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
+                SecureSettingsProto.SHOW_ROTATION_SUGGESTIONS);
+        dumpSetting(s, p,
+                Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED,
+                SecureSettingsProto.NUM_ROTATION_SUGGESTIONS_ACCEPTED);
+        dumpSetting(s, p,
                 Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
                 SecureSettingsProto.ENABLED_NOTIFICATION_ASSISTANT);
         dumpSetting(s, p,
@@ -1776,12 +1925,15 @@
         dumpSetting(s, p,
                 Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
                 SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING);
-
         // Please insert new settings using the same order as in Settings.Secure.
+
+        p.end(token);
     }
 
     private static void dumpProtoSystemSettingsLocked(
-            @NonNull SettingsState s, @NonNull ProtoOutputStream p) {
+            @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) {
+        final long token = p.start(fieldId);
+
         s.dumpHistoricalOperations(p, SystemSettingsProto.HISTORICAL_OPERATIONS);
 
         // This uses the same order as in Settings.System.
@@ -1794,11 +1946,11 @@
                 Settings.System.ADVANCED_SETTINGS,
                 SystemSettingsProto.ADVANCED_SETTINGS);
         // Settings.System.AIRPLANE_MODE_ON intentionally excluded since it's deprecated.
-        // Settings.System.RADIO_BLUETOOTH intentionally excluded since it's deprecated.
-        // Settings.System.RADIO_WIFI intentionally excluded since it's deprecated.
-        // Settings.System.RADIO_WIMAX intentionally excluded since it's deprecated.
-        // Settings.System.RADIO_CELL intentionally excluded since it's deprecated.
-        // Settings.System.RADIO_NFC intentionally excluded since it's deprecated.
+        // Settings.System.RADIO_BLUETOOTH intentionally excluded since it's just a constant.
+        // Settings.System.RADIO_WIFI intentionally excluded since it's just a constant.
+        // Settings.System.RADIO_WIMAX intentionally excluded since it's just a constant.
+        // Settings.System.RADIO_CELL intentionally excluded since it's just a constant.
+        // Settings.System.RADIO_NFC intentionally excluded since it's just a constant.
         // Settings.System.AIRPLANE_MODE_RADIOS intentionally excluded since it's deprecated.
         // Settings.System.AIRPLANE_MODE_TOGGLABLE_RADIOS intentionally excluded since it's deprecated.
         // Settings.System.WIFI_SLEEP_POLICY intentionally excluded since it's deprecated.
@@ -1861,6 +2013,12 @@
                 Settings.System.VIBRATE_INPUT_DEVICES,
                 SystemSettingsProto.VIBRATE_INPUT_DEVICES);
         dumpSetting(s, p,
+                Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
+                SystemSettingsProto.NOTIFICATION_VIBRATION_INTENSITY);
+        dumpSetting(s, p,
+                Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+                SystemSettingsProto.HAPTIC_FEEDBACK_INTENSITY);
+        dumpSetting(s, p,
                 Settings.System.VOLUME_RING,
                 SystemSettingsProto.VOLUME_RING);
         dumpSetting(s, p,
@@ -1973,6 +2131,9 @@
                 Settings.System.TTY_MODE,
                 SystemSettingsProto.TTY_MODE);
         dumpSetting(s, p,
+                Settings.System.RTT_CALLING_MODE,
+                SystemSettingsProto.RTT_CALLING_MODE);
+        dumpSetting(s, p,
                 Settings.System.SOUND_EFFECTS_ENABLED,
                 SystemSettingsProto.SOUND_EFFECTS_ENABLED);
         dumpSetting(s, p,
@@ -2038,5 +2199,7 @@
         // they're deprecated from Settings.System.
 
         // Please insert new settings using the same order as in Settings.System.
+
+        p.end(token);
     }
 }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 937b939..589ae2a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -118,6 +118,7 @@
     <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
     <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
     <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
+    <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.ACTIVITY_EMBEDDING" />
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index 6131acc..aa2fb32 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -16,6 +16,7 @@
 
 import android.graphics.Canvas;
 import android.view.MotionEvent;
+import android.view.View;
 
 import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
@@ -42,6 +43,8 @@
 
         public void onLayout(boolean changed, int left, int top, int right, int bottom);
 
+        public void onNavigationButtonLongPress(View v);
+
         public default void destroy() { }
     }
 
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 12fccd4..4d6509d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -401,9 +401,9 @@
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"Aucune\ninterruption"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
-    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement… (rechargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement rapide… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Rechargement lent… (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cce38f1..2c73f1e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -377,6 +377,9 @@
     <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
     <string name="data_connection_3_5g">3.5G</string>
 
+    <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_3_5g_plus">3.5G+</string>
+
     <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
     <string name="data_connection_4g">4G</string>
 
@@ -1059,6 +1062,9 @@
     <!-- The text to clear all notifications. [CHAR LIMIT=60] -->
     <string name="clear_all_notifications_text">Clear all</string>
 
+    <!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
+    <string name="dnd_suppressing_shade_text">Do Not disturb is hiding notifications</string>
+
     <!-- Media projection permission dialog action text. [CHAR LIMIT=60] -->
     <string name="media_projection_action_text">Start now</string>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index ef36610..8612445 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -80,4 +80,17 @@
      * Sent when overview is to be hidden.
      */
     void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+
+    /**
+     * Sent when a user swipes up over the navigation bar to launch overview. Swipe up is determined
+     * by passing the touch slop in the direction towards launcher from navigation bar. During and
+     * after this event is sent the caller will continue to send motion events. The motion
+     * {@param event} passed after the touch slop was exceeded will also be passed after by
+     * {@link onMotionEvent}. Since motion events will be sent, motion up or cancel can still be
+     * sent to cancel overview regardless the current state of launcher (eg. if overview is already
+     * visible, this event will still be sent if user swipes up). When this signal is sent,
+     * navigation bar will not handle any gestures such as quick scrub or switch and the home button
+     * will cancel (long) press.
+     */
+    void onQuickStep(in MotionEvent event);
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 846aadd..4799f39 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -36,11 +36,6 @@
     void startScreenPinning(int taskId) = 1;
 
     /**
-     * Called when the overview service has started the recents animation.
-     */
-    void onRecentsAnimationStarted() = 2;
-
-    /**
      * Specifies the text to be shown for onboarding the new swipe-up gesture to access recents.
      */
     void setRecentsOnboardingText(CharSequence text) = 3;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 9a7abf8..940c9ef 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -51,6 +51,14 @@
         }
     }
 
+    public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
+        try {
+            mAnimationController.setAnimationTargetsBehindSystemBars(behindSystemBars);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to set whether animation targets are behind system bars", e);
+        }
+    }
+
     public void finish(boolean toHome) {
         try {
             mAnimationController.finish(toHome);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java
index 5fff5fe..098698a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java
@@ -29,6 +29,11 @@
         mWrapped.addRemoteAnimation(transition, adapter.getWrapped());
     }
 
+    public void addRemoteAnimation(int transition, int activityTypeFilter,
+            RemoteAnimationAdapterCompat adapter) {
+        mWrapped.addRemoteAnimation(transition, activityTypeFilter, adapter.getWrapped());
+    }
+
     RemoteAnimationDefinition getWrapped() {
         return mWrapped;
     }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index a9c80c6..2de3ae2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -18,6 +18,7 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.app.WindowConfiguration;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -58,6 +59,8 @@
     public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
     public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 
+    public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+
     private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
 
     public static WindowManagerWrapper getInstance() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index f0952f9..08b4fee 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -182,6 +182,7 @@
             }
             button.setCompoundDrawables(iconDrawable, null, null, null);
             button.setOnClickListener(this);
+            button.setClickable(pendingIntent != null);
         }
 
         // Removing old views
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index cad155c..5fce0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -45,6 +45,7 @@
 import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -317,6 +318,8 @@
 
         mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext));
 
+        mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 041af0e..a4af6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -102,15 +102,6 @@
             }
         }
 
-        public void onRecentsAnimationStarted() {
-            long token = Binder.clearCallingIdentity();
-            try {
-                mHandler.post(OverviewProxyService.this::notifyRecentsAnimationStarted);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
         public void onSplitScreenInvoked() {
             long token = Binder.clearCallingIdentity();
             try {
@@ -283,9 +274,9 @@
         }
     }
 
-    private void notifyRecentsAnimationStarted() {
+    public void notifyQuickStepStarted() {
         for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
-            mConnectionCallbacks.get(i).onRecentsAnimationStarted();
+            mConnectionCallbacks.get(i).onQuickStepStarted();
         }
     }
 
@@ -300,7 +291,7 @@
 
     public interface OverviewProxyListener {
         default void onConnectionChanged(boolean isConnected) {}
-        default void onRecentsAnimationStarted() {}
+        default void onQuickStepStarted() {}
         default void onInteractionFlagsChanged(@InteractionType int flags) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index ec2390f..e790061 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -33,6 +33,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManager;
+import android.os.SystemProperties;
 import android.provider.Settings.Secure;
 import android.support.annotation.VisibleForTesting;
 import android.util.DisplayMetrics;
@@ -65,6 +66,8 @@
 public class ScreenDecorations extends SystemUI implements Tunable {
     public static final String SIZE = "sysui_rounded_size";
     public static final String PADDING = "sysui_rounded_content_padding";
+    private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
+            SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
 
     private int mRoundedDefault;
     private View mOverlay;
@@ -237,7 +240,12 @@
                         | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
-                | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+                | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+
+        if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
+            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
+        }
+
         lp.setTitle("ScreenDecorOverlay");
         lp.gravity = Gravity.TOP | Gravity.LEFT;
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 0486a9d..a4927b7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -63,7 +63,6 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
@@ -551,7 +550,6 @@
             alpha = (int) (interpolatedAlpha * 255);
         } else {
             if (mMenuState == MENU_STATE_CLOSE) {
-                mSettingsButton.setAlpha(menuAlpha);
                 mDismissButton.setAlpha(menuAlpha);
             }
             alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index d9359a4..c348187 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -189,7 +189,7 @@
         }
     }
 
-    public void onRecentsAnimationStarted() {
+    public void onQuickStepStarted() {
         boolean alreadySeenRecentsOnboarding = Prefs.getBoolean(mContext,
                 Prefs.Key.HAS_SEEN_RECENTS_ONBOARDING, false);
         if (!alreadySeenRecentsOnboarding) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 406eef8..f2a7adf 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -368,7 +368,9 @@
         } else {
             final int val = value + mMinimumBacklight;
             if (stopTracking) {
-                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
+                final int metric = mAutomatic ?
+                        MetricsEvent.ACTION_BRIGHTNESS_AUTO : MetricsEvent.ACTION_BRIGHTNESS;
+                MetricsLogger.action(mContext, metric, val);
             }
             setBrightness(val);
             if (!tracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index 58adde2..3698c3a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import android.annotation.ColorInt;
+import android.annotation.StringRes;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.util.AttributeSet;
@@ -30,6 +31,7 @@
 public class EmptyShadeView extends StackScrollerDecorView {
 
     private TextView mEmptyText;
+    private @StringRes int mText = R.string.empty_shade_text;
 
     public EmptyShadeView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -38,7 +40,7 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mEmptyText.setText(R.string.empty_shade_text);
+        mEmptyText.setText(mText);
     }
 
     @Override
@@ -50,6 +52,11 @@
         mEmptyText.setTextColor(color);
     }
 
+    public void setText(@StringRes int text) {
+        mText = text;
+        mEmptyText.setText(mText);
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 1109955..010b165 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -157,7 +157,7 @@
     public void onFullyHidden() {
         if (!mShowingSoon) {
             cancelShowRunnable();
-            inflateView();
+            mRoot.setVisibility(View.INVISIBLE);
             mFalsingManager.onBouncerHidden();
         }
     }
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 9fa06f7..ce8e746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -175,8 +175,8 @@
         }
 
         @Override
-        public void onRecentsAnimationStarted() {
-            mNavigationBarView.setRecentsAnimationStarted(true);
+        public void onQuickStepStarted() {
+            mNavigationBarView.onQuickStepStarted();
 
             // Use navbar dragging as a signal to hide the rotate button
             setRotateSuggestionButtonState(false);
@@ -751,6 +751,7 @@
         if (shouldDisableNavbarGestures()) {
             return false;
         }
+        mNavigationBarView.onNavigationButtonLongPress(v);
         mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
         mAssistManager.startAssist(new Bundle() /* args */);
         mStatusBar.awakenDreams();
@@ -787,10 +788,12 @@
     }
 
     private boolean onLongPressBackHome(View v) {
+        mNavigationBarView.onNavigationButtonLongPress(v);
         return onLongPressNavigationButtons(v, R.id.back, R.id.home);
     }
 
     private boolean onLongPressBackRecents(View v) {
+        mNavigationBarView.onNavigationButtonLongPress(v);
         return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 6a1ed51..cd000fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -19,31 +19,22 @@
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_TOP;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
 
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.Rect;
-import android.os.RemoteException;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
-import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.tuner.TunerService;
 
@@ -75,25 +66,14 @@
     private NavigationBarView mNavigationBarView;
     private boolean mIsVertical;
 
-    private final QuickScrubController mQuickScrubController;
+    private final QuickStepController mQuickStepController;
     private final int mScrollTouchSlop;
-    private final Matrix mTransformGlobalMatrix = new Matrix();
-    private final Matrix mTransformLocalMatrix = new Matrix();
     private final StatusBar mStatusBar;
     private int mTouchDownX;
     private int mTouchDownY;
     private boolean mDownOnRecents;
     private VelocityTracker mVelocityTracker;
-    private OverviewProxyService mOverviewProxyService = Dependency.get(OverviewProxyService.class);
-    private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
-        @Override
-        public void onRecentsAnimationStarted() {
-            mRecentsAnimationStarted = true;
-            mQuickScrubController.setRecentsAnimationStarted(true /* started */);
-        }
-    };
 
-    private boolean mRecentsAnimationStarted;
     private boolean mDockWindowEnabled;
     private boolean mDockWindowTouchSlopExceeded;
     private int mDragMode;
@@ -103,14 +83,12 @@
         mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
         Resources r = context.getResources();
         mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
-        mQuickScrubController = new QuickScrubController(context);
+        mQuickStepController = new QuickStepController(context);
         Dependency.get(TunerService.class).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
-        mOverviewProxyService.addCallback(mOverviewProxyListener);
     }
 
     public void destroy() {
         Dependency.get(TunerService.class).removeTunable(this);
-        mOverviewProxyService.removeCallback(mOverviewProxyListener);
     }
 
     public void setComponents(RecentsComponent recentsComponent, Divider divider,
@@ -118,65 +96,19 @@
         mRecentsComponent = recentsComponent;
         mDivider = divider;
         mNavigationBarView = navigationBarView;
-        mQuickScrubController.setComponents(mNavigationBarView);
+        mQuickStepController.setComponents(mNavigationBarView);
     }
 
     public void setBarState(boolean isVertical, boolean isRTL) {
         mIsVertical = isVertical;
-        mQuickScrubController.setBarState(isVertical, isRTL);
-    }
-
-    private boolean proxyMotionEvents(MotionEvent event) {
-        final IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
-        if (overviewProxy != null && mNavigationBarView.isQuickStepSwipeUpEnabled()) {
-            mNavigationBarView.requestUnbufferedDispatch(event);
-            event.transform(mTransformGlobalMatrix);
-            try {
-                if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-                    overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
-                }
-                overviewProxy.onMotionEvent(event);
-                if (DEBUG_OVERVIEW_PROXY) {
-                    Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
-                }
-                return true;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Callback failed", e);
-            } finally {
-                event.transform(mTransformLocalMatrix);
-            }
-        }
-        return false;
+        mQuickStepController.setBarState(isVertical, isRTL);
     }
 
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()
-                || !mStatusBar.isPresenterFullyCollapsed()) {
+        if (!canHandleGestures()) {
             return false;
         }
-
-        int action = event.getActionMasked();
-        switch (action) {
-            case MotionEvent.ACTION_DOWN: {
-                mTouchDownX = (int) event.getX();
-                mTouchDownY = (int) event.getY();
-                mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
-                mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
-                mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
-                mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
-                mRecentsAnimationStarted = false;
-                mQuickScrubController.setRecentsAnimationStarted(false /* started */);
-                break;
-            }
-        }
-        boolean handledByQuickscrub = mQuickScrubController.onInterceptTouchEvent(event);
-        if (!handledByQuickscrub) {
-            // Proxy motion events until we start intercepting for quickscrub
-            proxyMotionEvents(event);
-        }
-
-        boolean result = handledByQuickscrub;
-        result |= mRecentsAnimationStarted;
+        boolean result = mQuickStepController.onInterceptTouchEvent(event);
         if (mDockWindowEnabled) {
             result |= interceptDockWindowEvent(event);
         }
@@ -184,18 +116,10 @@
     }
 
     public boolean onTouchEvent(MotionEvent event) {
-        if (mNavigationBarView.inScreenPinning() || mStatusBar.isKeyguardShowing()
-                || !mStatusBar.isPresenterFullyCollapsed()) {
+        if (!canHandleGestures()) {
             return false;
         }
-
-        // The same down event was just sent on intercept and therefore can be ignored here
-        boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
-                && mOverviewProxyService.getProxy() != null;
-        boolean result = mQuickScrubController.onTouchEvent(event)
-                || ignoreProxyDownEvent
-                || proxyMotionEvents(event);
-        result |= mRecentsAnimationStarted;
+        boolean result = mQuickStepController.onTouchEvent(event);
         if (mDockWindowEnabled) {
             result |= handleDockWindowEvent(event);
         }
@@ -203,17 +127,19 @@
     }
 
     public void onDraw(Canvas canvas) {
-        if (mNavigationBarView.isQuickScrubEnabled()) {
-            mQuickScrubController.onDraw(canvas);
-        }
+        mQuickStepController.onDraw(canvas);
     }
 
     public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        mQuickScrubController.onLayout(changed, left, top, right, bottom);
+        mQuickStepController.onLayout(changed, left, top, right, bottom);
     }
 
     public void onDarkIntensityChange(float intensity) {
-        mQuickScrubController.onDarkIntensityChange(intensity);
+        mQuickStepController.onDarkIntensityChange(intensity);
+    }
+
+    public void onNavigationButtonLongPress(View v) {
+        mQuickStepController.onNavigationButtonLongPress(v);
     }
 
     private boolean interceptDockWindowEvent(MotionEvent event) {
@@ -342,6 +268,11 @@
         mVelocityTracker = null;
     }
 
+    private boolean canHandleGestures() {
+        return !mNavigationBarView.inScreenPinning() && !mStatusBar.isKeyguardShowing()
+                && mStatusBar.isPresenterFullyCollapsed();
+    }
+
     private int calculateDragMode() {
         if (mIsVertical && !mDivider.getView().isHorizontalDivision()) {
             return DRAG_MODE_DIVIDER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 03efbb2..fcbd37c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -247,7 +247,7 @@
 
         mOverviewProxyService = Dependency.get(OverviewProxyService.class);
         mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
-        mVibratorHelper = new VibratorHelper(context);
+        mVibratorHelper = Dependency.get(VibratorHelper.class);
 
         mConfiguration = new Configuration();
         mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -290,18 +290,12 @@
         notifyVerticalChangedListener(mVertical);
     }
 
-    public void setRecentsAnimationStarted(boolean started) {
+    public void onQuickStepStarted() {
         if (mRecentsOnboarding != null) {
-            mRecentsOnboarding.onRecentsAnimationStarted();
+            mRecentsOnboarding.onQuickStepStarted();
         }
     }
 
-    public void onConnectionChanged(boolean isConnected) {
-        updateSlippery();
-        updateNavButtonIcons();
-        setUpSwipeUpOnboarding(isConnected);
-    }
-
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         switch (event.getActionMasked()) {
@@ -675,6 +669,10 @@
         }
     }
 
+    public void onNavigationButtonLongPress(View v) {
+        mGestureHelper.onNavigationButtonLongPress(v);
+    }
+
     public void onPanelExpandedChange(boolean expanded) {
         updateSlippery();
     }
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 3de0a41..7f1e9d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -38,6 +38,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.LatencyTracker;
 import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
@@ -207,7 +208,7 @@
         mFalsingManager = FalsingManager.getInstance(context);
         mNotificationsDragEnabled =
                 getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
-        mVibratorHelper = new VibratorHelper(context);
+        mVibratorHelper = Dependency.get(VibratorHelper.class);
         mVibrateOnOpening = mContext.getResources().getBoolean(
                 R.bool.config_vibrateOnIconAnimation);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
similarity index 65%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 00aff53..19544b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -55,10 +56,10 @@
 /**
  * Class to detect gestures on the navigation bar and implement quick scrub and switch.
  */
-public class QuickScrubController extends GestureDetector.SimpleOnGestureListener implements
+public class QuickStepController extends GestureDetector.SimpleOnGestureListener implements
         GestureHelper {
 
-    private static final String TAG = "QuickScrubController";
+    private static final String TAG = "QuickStepController";
     private static final int QUICK_SWITCH_FLING_VELOCITY = 0;
     private static final int ANIM_DURATION_MS = 200;
     private static final long LONG_PRESS_DELAY_MS = 225;
@@ -75,7 +76,8 @@
     private boolean mDraggingActive;
     private boolean mQuickScrubActive;
     private boolean mAllowQuickSwitch;
-    private boolean mRecentsAnimationStarted;
+    private boolean mAllowGestureDetection;
+    private boolean mQuickStepStarted;
     private float mDownOffset;
     private float mTranslation;
     private int mTouchDownX;
@@ -101,6 +103,8 @@
     private final ValueAnimator mButtonAnimator;
     private final AnimatorSet mQuickScrubEndAnimator;
     private final Context mContext;
+    private final Matrix mTransformGlobalMatrix = new Matrix();
+    private final Matrix mTransformLocalMatrix = new Matrix();
     private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
 
     private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
@@ -123,7 +127,6 @@
     private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
-            mNavigationBarView.getHomeButton().setClickable(true);
             mQuickScrubActive = false;
             mTranslation = 0;
             mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
@@ -165,7 +168,7 @@
             }
         };
 
-    public QuickScrubController(Context context) {
+    public QuickStepController(Context context) {
         mContext = context;
         mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mOverviewEventSender = Dependency.get(OverviewProxyService.class);
@@ -197,31 +200,35 @@
      */
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
-        if (!mNavigationBarView.isQuickScrubEnabled()) {
-            homeButton.setDelayTouchFeedback(false);
-            return false;
-        }
-
         return handleTouchEvent(event);
     }
 
     /**
-     * @return true if we want to handle touch events for quick scrub/switch and prevent proxying
-     *         the event to the overview service.
+     * @return true if we want to handle touch events for quick scrub/switch or if down event (that
+     *         will get consumed and ignored). No events will be proxied to the overview service.
      */
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        return handleTouchEvent(event);
+        // The same down event was just sent on intercept and therefore can be ignored here
+        final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
+                && mOverviewEventSender.getProxy() != null;
+        return ignoreProxyDownEvent || handleTouchEvent(event);
     }
 
     private boolean handleTouchEvent(MotionEvent event) {
-        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+        if (!mNavigationBarView.isQuickScrubEnabled()
+                && !mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+            mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
+            return false;
+        }
+        mNavigationBarView.requestUnbufferedDispatch(event);
+
         final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
         if (mGestureDetector.onTouchEvent(event)) {
             // If the fling has been handled on UP, then skip proxying the UP
             return true;
         }
+        final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
         int action = event.getAction();
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN: {
@@ -232,89 +239,99 @@
                     mQuickScrubEndAnimator.end();
                 }
                 mHomeButtonView = homeButton.getCurrentView();
-                if (mNavigationBarView.isQuickScrubEnabled()
-                        && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME) {
-                    mTouchDownX = x;
-                    mTouchDownY = y;
-                    homeButton.setDelayTouchFeedback(true);
+                homeButton.setDelayTouchFeedback(true /* delay */);
+                mTouchDownX = x;
+                mTouchDownY = y;
+                if (homePressed) {
                     mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS);
-                } else {
-                    homeButton.setDelayTouchFeedback(false);
-                    mTouchDownX = mTouchDownY = -1;
                 }
+                mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
+                mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
+                mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
+                mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
+                mQuickStepStarted = false;
                 mAllowQuickSwitch = true;
+                mAllowGestureDetection = true;
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
-                if (mTouchDownX != -1) {
-                    int x = (int) event.getX();
-                    int y = (int) event.getY();
-                    int xDiff = Math.abs(x - mTouchDownX);
-                    int yDiff = Math.abs(y - mTouchDownY);
-                    boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
-                    boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
-                    boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
-                    int pos, touchDown, offset, trackSize;
+                if (mQuickStepStarted || !mAllowGestureDetection){
+                    break;
+                }
+                int x = (int) event.getX();
+                int y = (int) event.getY();
+                int xDiff = Math.abs(x - mTouchDownX);
+                int yDiff = Math.abs(y - mTouchDownY);
+                boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
+                boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
+                boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
+                int pos, touchDown, offset, trackSize;
 
-                    if (mIsVertical) {
-                        exceededTouchSlop = exceededTouchSlopY;
-                        exceededPerpendicularTouchSlop = exceededTouchSlopX;
-                        pos = y;
-                        touchDown = mTouchDownY;
-                        offset = pos - mTrackRect.top;
-                        trackSize = mTrackRect.height();
-                    } else {
-                        exceededTouchSlop = exceededTouchSlopX;
-                        exceededPerpendicularTouchSlop = exceededTouchSlopY;
-                        pos = x;
-                        touchDown = mTouchDownX;
-                        offset = pos - mTrackRect.left;
-                        trackSize = mTrackRect.width();
+                if (mIsVertical) {
+                    exceededTouchSlop = exceededTouchSlopY;
+                    exceededPerpendicularTouchSlop = exceededTouchSlopX;
+                    pos = y;
+                    touchDown = mTouchDownY;
+                    offset = pos - mTrackRect.top;
+                    trackSize = mTrackRect.height();
+                } else {
+                    exceededTouchSlop = exceededTouchSlopX;
+                    exceededPerpendicularTouchSlop = exceededTouchSlopY;
+                    pos = x;
+                    touchDown = mTouchDownX;
+                    offset = pos - mTrackRect.left;
+                    trackSize = mTrackRect.width();
+                }
+                // Decide to start quickstep if dragging away from the navigation bar, otherwise in
+                // the parallel direction, decide to start quickscrub. Only one may run.
+                if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
+                    if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
+                        startQuickStep(event);
                     }
-                    // Do not start scrubbing when dragging in the perpendicular direction if we
-                    // haven't already started quickscrub
-                    if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
-                        mHandler.removeCallbacksAndMessages(null);
-                        return false;
-                    }
-                    if (!mDragPositive) {
-                        offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
-                    }
+                    break;
+                }
 
-                    // Control the button movement
-                    if (!mDraggingActive && exceededTouchSlop && !mRecentsAnimationStarted) {
-                        boolean allowDrag = !mDragPositive
-                                ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
-                        if (allowDrag) {
-                            mDownOffset = offset;
-                            homeButton.setClickable(false);
-                            mDraggingActive = true;
-                        }
+                // Do not handle quick scrub/switch if disabled or hit target is not home button
+                if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) {
+                    break;
+                }
+
+                if (!mDragPositive) {
+                    offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
+                }
+
+                // Control the button movement
+                if (!mDraggingActive && exceededTouchSlop) {
+                    boolean allowDrag = !mDragPositive
+                            ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
+                    if (allowDrag) {
+                        mDownOffset = offset;
+                        homeButton.abortCurrentGesture();
+                        mDraggingActive = true;
                     }
-                    if (mDraggingActive && (mDragPositive && offset >= 0
-                            || !mDragPositive && offset <= 0)) {
-                        float scrubFraction =
-                                Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
-                        mTranslation = !mDragPositive
-                            ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
-                            : Utilities.clamp(offset - mDownOffset, 0, trackSize);
-                        if (mQuickScrubActive) {
-                            try {
-                                mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
-                                if (DEBUG_OVERVIEW_PROXY) {
-                                    Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
-                                }
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Failed to send progress of quick scrub.", e);
+                }
+                if (mDraggingActive && (mDragPositive && offset >= 0
+                        || !mDragPositive && offset <= 0)) {
+                    float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
+                    mTranslation = !mDragPositive
+                        ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
+                        : Utilities.clamp(offset - mDownOffset, 0, trackSize);
+                    if (mQuickScrubActive) {
+                        try {
+                            mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
+                            if (DEBUG_OVERVIEW_PROXY) {
+                                Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
                             }
-                        } else {
-                            mTranslation /= SWITCH_STICKINESS;
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Failed to send progress of quick scrub.", e);
                         }
-                        if (mIsVertical) {
-                            mHomeButtonView.setTranslationY(mTranslation);
-                        } else {
-                            mHomeButtonView.setTranslationX(mTranslation);
-                        }
+                    } else {
+                        mTranslation /= SWITCH_STICKINESS;
+                    }
+                    if (mIsVertical) {
+                        mHomeButtonView.setTranslationY(mTranslation);
+                    } else {
+                        mHomeButtonView.setTranslationX(mTranslation);
                     }
                 }
                 break;
@@ -324,11 +341,20 @@
                 endQuickScrub(true /* animate */);
                 break;
         }
-        return mDraggingActive || mQuickScrubActive;
+
+        // Proxy motion events to launcher if not handled by quick scrub/switch
+        boolean handled = mDraggingActive || mQuickScrubActive;
+        if (!handled && mAllowGestureDetection) {
+            proxyMotionEvents(event);
+        }
+        return handled || mQuickStepStarted;
     }
 
     @Override
     public void onDraw(Canvas canvas) {
+        if (mNavigationBarView.isQuickScrubEnabled()) {
+            return;
+        }
         int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
                 mDarkTrackColor);
         mTrackPaint.setColor(color);
@@ -381,6 +407,31 @@
         }
     }
 
+    @Override
+    public void onNavigationButtonLongPress(View v) {
+        mAllowGestureDetection = false;
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
+    private void startQuickStep(MotionEvent event) {
+        mQuickStepStarted = true;
+        event.transform(mTransformGlobalMatrix);
+        try {
+            mOverviewEventSender.getProxy().onQuickStep(event);
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Step Start");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send quick step started.", e);
+        } finally {
+            event.transform(mTransformLocalMatrix);
+        }
+        mOverviewEventSender.notifyQuickStepStarted();
+        mNavigationBarView.getHomeButton().abortCurrentGesture();
+        cancelQuickSwitch();
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
     private void startQuickScrub() {
         if (!mQuickScrubActive && mDraggingActive) {
             mQuickScrubActive = true;
@@ -396,9 +447,6 @@
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to send start of quick scrub.", e);
             }
-        } else {
-            // After long press do not allow quick scrub/switch
-            mTouchDownX = -1;
         }
     }
 
@@ -421,11 +469,24 @@
         mDraggingActive = false;
     }
 
-    public void setRecentsAnimationStarted(boolean started) {
-        mRecentsAnimationStarted = started;
-        if (started) {
-            cancelQuickSwitch();
+    private boolean proxyMotionEvents(MotionEvent event) {
+        final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
+        event.transform(mTransformGlobalMatrix);
+        try {
+            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+                overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+            }
+            overviewProxy.onMotionEvent(event);
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
+            }
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Callback failed", e);
+        } finally {
+            event.transform(mTransformLocalMatrix);
         }
+        return false;
     }
 
     public void cancelQuickSwitch() {
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 5c77524..2e45b12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -232,6 +232,7 @@
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.util.NotificationChannels;
 import com.android.systemui.volume.VolumeComponent;
@@ -407,6 +408,7 @@
     protected NotificationEntryManager mEntryManager;
     protected NotificationViewHierarchyManager mViewHierarchyManager;
     protected AppOpsListener mAppOpsListener;
+    private ZenModeController mZenController;
 
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -626,6 +628,7 @@
         mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
         mAppOpsListener = Dependency.get(AppOpsListener.class);
         mAppOpsListener.setUpWithPresenter(this, mEntryManager);
+        mZenController = Dependency.get(ZenModeController.class);
 
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
         mColorExtractor.addOnColorsChangedListener(this);
@@ -1166,6 +1169,7 @@
         }
         mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
                 R.layout.status_bar_no_notifications, mStackScroller, false);
+        mEmptyShadeView.setText(R.string.empty_shade_text);
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
     }
 
@@ -1498,6 +1502,9 @@
         return entry.row.getParent() instanceof NotificationStackScrollLayout;
     }
 
+    public boolean areNotificationsHidden() {
+        return mZenController.areNotificationsHiddenInShade();
+    }
 
     public void requestNotificationUpdate() {
         mEntryManager.updateNotifications();
@@ -4624,8 +4631,9 @@
                 != FingerprintUnlockController.MODE_UNLOCK);
 
         if (mBouncerShowing) {
-            mScrimController.transitionTo(
-                    mIsOccluded ? ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER);
+            final boolean qsExpanded = mQSPanel != null && mQSPanel.isExpanded();
+            mScrimController.transitionTo(mIsOccluded || qsExpanded ?
+                    ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER);
         } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) {
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         } else if (mBrightnessMirrorVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 81641da..e5fefd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -126,7 +126,7 @@
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
         mRipple = new KeyButtonRipple(context, this);
-        mVibratorHelper = new VibratorHelper(context);
+        mVibratorHelper = Dependency.get(VibratorHelper.class);
         mOverviewProxyService = Dependency.get(OverviewProxyService.class);
         setBackground(mRipple);
     }
@@ -224,8 +224,10 @@
             case MotionEvent.ACTION_DOWN:
                 mDownTime = SystemClock.uptimeMillis();
                 mLongClicked = false;
-                mTouchDownX = (int) ev.getX();
-                mTouchDownY = (int) ev.getY();
+
+                // Use raw X and Y to detect gestures in case a parent changes the x and y values
+                mTouchDownX = (int) ev.getRawX();
+                mTouchDownY = (int) ev.getRawY();
                 if (mCode != 0) {
                     sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
                 } else {
@@ -241,8 +243,8 @@
                 postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
                 break;
             case MotionEvent.ACTION_MOVE:
-                x = (int)ev.getX();
-                y = (int)ev.getY();
+                x = (int)ev.getRawX();
+                y = (int)ev.getRawY();
                 boolean exceededTouchSlopX = Math.abs(x - mTouchDownX) > mTouchSlop;
                 boolean exceededTouchSlopY = Math.abs(y - mTouchDownY) > mTouchSlop;
                 if (exceededTouchSlopX || exceededTouchSlopY) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 487d1c5..a046675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -205,13 +205,15 @@
         }
 
         MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+        MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
         if (mConfig.hspaDataDistinguishable) {
             hGroup = TelephonyIcons.H;
+            hPlusGroup = TelephonyIcons.H_PLUS;
         }
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
-        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
+        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup);
 
         if (mConfig.show4gForLte) {
             mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5363742..2258fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -884,6 +884,7 @@
                             datatype.equals("e") ? TelephonyIcons.E :
                             datatype.equals("g") ? TelephonyIcons.G :
                             datatype.equals("h") ? TelephonyIcons.H :
+                            datatype.equals("h+") ? TelephonyIcons.H_PLUS :
                             datatype.equals("lte") ? TelephonyIcons.LTE :
                             datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
                             datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 986abef..7e6fe02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -28,7 +28,6 @@
     static final int ICON_G = R.drawable.ic_g_mobiledata;
     static final int ICON_E = R.drawable.ic_e_mobiledata;
     static final int ICON_H = R.drawable.ic_h_mobiledata;
-    // TODO: add logic to insert H+ icon
     static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
     static final int ICON_3G = R.drawable.ic_3g_mobiledata;
     static final int ICON_4G = R.drawable.ic_4g_mobiledata;
@@ -135,6 +134,19 @@
             TelephonyIcons.ICON_H,
             false);
 
+    static final MobileIconGroup H_PLUS = new MobileIconGroup(
+            "H+",
+            null,
+            null,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            0,
+            0,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.data_connection_3_5g_plus,
+            TelephonyIcons.ICON_H_PLUS,
+            false);
+
     static final MobileIconGroup FOUR_G = new MobileIconGroup(
             "4G",
             null,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 8777aa6..4ee8059 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -35,6 +35,7 @@
     boolean isCountdownConditionSupported();
     int getCurrentUser();
     boolean isVolumeRestricted();
+    boolean areNotificationsHiddenInShade();
 
     public static interface Callback {
         default void onZenChanged(int zen) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 0fd2445..a9da239 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -33,13 +33,11 @@
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.service.notification.Condition;
-import android.service.notification.IConditionListener;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ZenRule;
-import android.support.annotation.VisibleForTesting;
 import android.util.Log;
-import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.util.Utils;
@@ -64,9 +62,9 @@
     private final UserManager mUserManager;
 
     private int mUserId;
-    private boolean mRequesting;
     private boolean mRegistered;
     private ZenModeConfig mConfig;
+    private int mZenMode;
 
     public ZenModeControllerImpl(Context context, Handler handler) {
         super(context);
@@ -74,6 +72,7 @@
         mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
             @Override
             protected void handleValueChanged(int value) {
+                updateZenMode(value);
                 fireZenChanged(value);
             }
         };
@@ -86,7 +85,9 @@
         mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
         mConfig = mNoMan.getZenModeConfig();
         mModeSetting.setListening(true);
+        updateZenMode(mModeSetting.getValue());
         mConfigSetting.setListening(true);
+        updateZenModeConfig();
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mSetupObserver = new SetupObserver(handler);
         mSetupObserver.register();
@@ -101,6 +102,15 @@
     }
 
     @Override
+    public boolean areNotificationsHiddenInShade() {
+        if (mZenMode != Global.ZEN_MODE_OFF) {
+            return (mConfig.suppressedVisualEffects & NotificationManager.Policy
+                    .SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
+        }
+        return false;
+    }
+
+    @Override
     public void addCallback(Callback callback) {
         mCallbacks.add(callback);
     }
@@ -186,10 +196,6 @@
         Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
     }
 
-    private void fireConditionsChanged(Condition[] conditions) {
-        Utils.safeForeach(mCallbacks, c -> c.onConditionsChanged(conditions));
-    }
-
     private void fireManualRuleChanged(ZenRule rule) {
         Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
     }
@@ -199,17 +205,13 @@
         Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
     }
 
-    private void updateConditions(Condition[] conditions) {
-        if (conditions == null || conditions.length == 0) return;
-        for (Condition c : conditions) {
-            if ((c.flags & Condition.FLAG_RELEVANT_NOW) == 0) continue;
-            mConditions.put(c.id, c);
-        }
-        fireConditionsChanged(
-                mConditions.values().toArray(new Condition[mConditions.values().size()]));
+    @VisibleForTesting
+    protected void updateZenMode(int mode) {
+        mZenMode = mode;
     }
 
-    private void updateZenModeConfig() {
+    @VisibleForTesting
+    protected void updateZenModeConfig() {
         final ZenModeConfig config = mNoMan.getZenModeConfig();
         if (Objects.equals(config, mConfig)) return;
         final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
@@ -220,16 +222,6 @@
         fireManualRuleChanged(newRule);
     }
 
-    private final IConditionListener mListener = new IConditionListener.Stub() {
-        @Override
-        public void onConditionsReceived(Condition[] conditions) {
-            if (DEBUG) Slog.d(TAG, "onConditionsReceived "
-                    + (conditions == null ? 0 : conditions.length) + " mRequesting=" + mRequesting);
-            if (!mRequesting) return;
-            updateConditions(conditions);
-        }
-    };
-
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 66fde79..a85f4e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -104,7 +104,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -3985,6 +3984,11 @@
                 } else {
                     mEmptyShadeView.setInvisible();
                 }
+                if (mStatusBar.areNotificationsHidden()) {
+                    mEmptyShadeView.setText(R.string.dnd_suppressing_shade_text);
+                } else {
+                    mEmptyShadeView.setText(R.string.empty_shade_text);
+                }
                 mEmptyShadeView.setVisibility(newVisibility);
                 mEmptyShadeView.setWillBeGone(false);
                 updateContentHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 22bf983..91314fe 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -479,6 +479,7 @@
         if (mShowing) return;
         mShowing = true;
 
+        initSettingsH();
         mDialog.show();
         Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
         mController.notifyVisible(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 8629799..365a9b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -74,6 +74,17 @@
         verifyDataIndicators(TelephonyIcons.ICON_H);
     }
 
+
+    @Test
+    public void testHspaPlusDataIcon() {
+        setupDefaultSignal();
+        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+                TelephonyManager.NETWORK_TYPE_HSPAP);
+
+        verifyDataIndicators(TelephonyIcons.ICON_H_PLUS);
+    }
+
+
     @Test
     public void testWfcNoDataIcon() {
         setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
index 8124bf3..da8017e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -14,11 +14,17 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.app.NotificationManager;
 import android.os.Handler;
+import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -27,8 +33,11 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.ZenModeController.Callback;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -36,21 +45,64 @@
 public class ZenModeControllerImplTest extends SysuiTestCase {
 
     private Callback mCallback;
+    @Mock
+    NotificationManager mNm;
+    @Mock
+    ZenModeConfig mConfig;
+
+    private ZenModeControllerImpl mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext.addMockSystemService(NotificationManager.class, mNm);
+        when(mNm.getZenModeConfig()).thenReturn(mConfig);
+
+        mController = new ZenModeControllerImpl(mContext, new Handler());
+    }
 
     @Test
     public void testRemoveDuringCallback() {
-        ZenModeControllerImpl controller = new ZenModeControllerImpl(mContext, new Handler());
         mCallback = new Callback() {
             @Override
             public void onConfigChanged(ZenModeConfig config) {
-                controller.removeCallback(mCallback);
+                mController.removeCallback(mCallback);
             }
         };
-        controller.addCallback(mCallback);
+        mController.addCallback(mCallback);
         Callback mockCallback = mock(Callback.class);
-        controller.addCallback(mockCallback);
-        controller.fireConfigChanged(null);
+        mController.addCallback(mockCallback);
+        mController.fireConfigChanged(null);
         verify(mockCallback).onConfigChanged(eq(null));
     }
 
+    @Test
+    public void testAreNotificationsHiddenInShade_zenOffShadeSuppressed() {
+        mConfig.suppressedVisualEffects =
+                NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+        mController.updateZenMode(Settings.Global.ZEN_MODE_OFF);
+        mController.updateZenModeConfig();
+
+        assertFalse(mController.areNotificationsHiddenInShade());
+    }
+
+    @Test
+    public void testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() {
+        mConfig.suppressedVisualEffects =
+                NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+        mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        mController.updateZenModeConfig();
+
+        assertFalse(mController.areNotificationsHiddenInShade());
+    }
+
+    @Test
+    public void testAreNotificationsHiddenInShade_zenOnShadeSuppressed() {
+        mConfig.suppressedVisualEffects =
+                NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+        mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+        mController.updateZenModeConfig();
+
+        assertTrue(mController.areNotificationsHiddenInShade());
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index d9673d3..6fa91ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -17,17 +17,16 @@
 package com.android.systemui.statusbar.stack;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.annotation.UiThread;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.NotificationHeaderView;
-import android.view.View;
 
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -72,4 +71,27 @@
                 0.01 /* delta */);
     }
 
+    @Test
+    public void updateEmptyView_dndSuppressing() {
+        EmptyShadeView view = mock(EmptyShadeView.class);
+        mStackScroller.setEmptyShadeView(view);
+        when(view.willBeGone()).thenReturn(true);
+        when(mBar.areNotificationsHidden()).thenReturn(true);
+
+        mStackScroller.updateEmptyShadeView(true);
+
+        verify(view).setText(R.string.dnd_suppressing_shade_text);
+    }
+
+    @Test
+    public void updateEmptyView_dndNotSuppressing() {
+        EmptyShadeView view = mock(EmptyShadeView.class);
+        mStackScroller.setEmptyShadeView(view);
+        when(view.willBeGone()).thenReturn(true);
+        when(mBar.areNotificationsHidden()).thenReturn(false);
+
+        mStackScroller.updateEmptyShadeView(true);
+
+        verify(view).setText(R.string.empty_shade_text);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
index fb9bf7a..86c43c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
@@ -77,4 +77,9 @@
     public boolean isVolumeRestricted() {
         return false;
     }
+
+    @Override
+    public boolean areNotificationsHiddenInShade() {
+        return false;
+    }
 }
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
new file mode 100644
index 0000000..d83b30a
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := DisplayCutoutEmulationDouble
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := DisplayCutoutEmulationDoubleOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..5d3385d
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.display.cutout.emulation.double"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.display_cutout_emulation"
+        android:priority="1"/>
+
+    <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
new file mode 100644
index 0000000..ca261f9
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -0,0 +1,67 @@
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- The bounding path of the cutout region of the main built-in display.
+         Must either be empty if there is no cutout region, or a string that is parsable by
+         {@link android.util.PathParser}.
+
+         The path is assumed to be specified in display coordinates with pixel units and in
+         the display's native orientation, with the origin of the coordinate system at the
+         center top of the display.
+
+         To facilitate writing device-independent emulation overlays, the marker `@dp` can be
+         appended after the path string to interpret coordinates in dp instead of px units.
+         Note that a physical cutout should be configured in pixels for the best results.
+         -->
+    <string translatable="false" name="config_mainBuiltInDisplayCutout">
+        M 0,0
+        L -72, 0
+        L -69.9940446283, 20.0595537175
+        C -69.1582133885, 28.4178661152 -65.2, 32.0 -56.8, 32.0
+        L 56.8, 32.0
+        C 65.2, 32.0 69.1582133885, 28.4178661152 69.9940446283, 20.0595537175
+        L 72, 0
+        Z
+        @bottom
+        M 0,0
+        L -72, 0
+        L -69.9940446283, -20.0595537175
+        C -69.1582133885, -28.4178661152 -65.2, -32.0 -56.8, -32.0
+        L 56.8, -32.0
+        C 65.2, -32.0 69.1582133885, -28.4178661152 69.9940446283, -20.0595537175
+        L 72, 0
+        Z
+        @dp
+    </string>
+
+    <!-- Whether the display cutout region of the main built-in display should be forced to
+         black in software (to avoid aliasing or emulate a cutout that is not physically existent).
+     -->
+    <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
+
+    <!-- Height of the status bar -->
+    <dimen name="status_bar_height_portrait">48dp</dimen>
+    <dimen name="status_bar_height_landscape">28dp</dimen>
+    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+    <dimen name="quick_qs_offset_height">48dp</dimen>
+    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+    <dimen name="quick_qs_total_height">176dp</dimen>
+
+</resources>
+
+
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
new file mode 100644
index 0000000..68c2dcb
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="display_cutout_emulation_overlay">Double display cutout</string>
+
+</resources>
+
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 07012d8..d89cc96 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5499,6 +5499,10 @@
     // OS: P
     SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357;
 
+    // Action: notification shade > manage notifications
+    // OS: P
+    ACTION_MANAGE_NOTIFICATIONS = 1358;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index 99160c2..dd6e6ab 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -18,53 +18,76 @@
 
 import android.app.AlarmManager;
 import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.Handler;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.KeyValueListParser;
+import android.util.KeyValueSettingObserver;
 import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
 
 /**
  * Class to access backup manager constants.
  *
- * The backup manager constants are encoded as a key value list separated by commas
- * and stored as a Settings.Secure.
+ * <p>The backup manager constants are encoded as a key value list separated by commas and stored as
+ * a Settings.Secure.
  */
-class BackupManagerConstants extends ContentObserver {
+class BackupManagerConstants extends KeyValueSettingObserver {
     private static final String TAG = "BackupManagerConstants";
+    private static final String SETTING = Settings.Secure.BACKUP_MANAGER_CONSTANTS;
 
     // Key names stored in the secure settings value.
-    private static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
+    @VisibleForTesting
+    public static final String KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
             "key_value_backup_interval_milliseconds";
-    private static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
+
+    @VisibleForTesting
+    public static final String KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
             "key_value_backup_fuzz_milliseconds";
-    private static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING =
+
+    @VisibleForTesting
+    public static final String KEY_VALUE_BACKUP_REQUIRE_CHARGING =
             "key_value_backup_require_charging";
-    private static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE =
+
+    @VisibleForTesting
+    public static final String KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE =
             "key_value_backup_required_network_type";
-    private static final String FULL_BACKUP_INTERVAL_MILLISECONDS =
+
+    @VisibleForTesting
+    public static final String FULL_BACKUP_INTERVAL_MILLISECONDS =
             "full_backup_interval_milliseconds";
-    private static final String FULL_BACKUP_REQUIRE_CHARGING =
-            "full_backup_require_charging";
-    private static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE =
+
+    @VisibleForTesting
+    public static final String FULL_BACKUP_REQUIRE_CHARGING = "full_backup_require_charging";
+
+    @VisibleForTesting
+    public static final String FULL_BACKUP_REQUIRED_NETWORK_TYPE =
             "full_backup_required_network_type";
-    private static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
+
+    @VisibleForTesting
+    public static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
             "backup_finished_notification_receivers";
 
     // Hard coded default values.
-    private static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
+    @VisibleForTesting
+    public static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
             4 * AlarmManager.INTERVAL_HOUR;
-    private static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS =
-            10 * 60 * 1000;
-    private static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true;
-    private static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1;
-    private static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS =
+
+    @VisibleForTesting
+    public static final long DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS = 10 * 60 * 1000;
+
+    @VisibleForTesting public static final boolean DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING = true;
+    @VisibleForTesting public static final int DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE = 1;
+
+    @VisibleForTesting
+    public static final long DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS =
             24 * AlarmManager.INTERVAL_HOUR;
-    private static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true;
-    private static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2;
-    private static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";
+
+    @VisibleForTesting public static final boolean DEFAULT_FULL_BACKUP_REQUIRE_CHARGING = true;
+    @VisibleForTesting public static final int DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE = 2;
+
+    @VisibleForTesting
+    public static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";
 
     // Backup manager constants.
     private long mKeyValueBackupIntervalMilliseconds;
@@ -76,49 +99,46 @@
     private int mFullBackupRequiredNetworkType;
     private String[] mBackupFinishedNotificationReceivers;
 
-    private ContentResolver mResolver;
-    private final KeyValueListParser mParser = new KeyValueListParser(',');
-
     public BackupManagerConstants(Handler handler, ContentResolver resolver) {
-        super(handler);
-        mResolver = resolver;
-        updateSettings();
-        mResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS), false, this);
+        super(handler, resolver, Settings.Secure.getUriFor(SETTING));
     }
 
-    @Override
-    public void onChange(boolean selfChange, Uri uri) {
-        updateSettings();
+    public String getSettingValue(ContentResolver resolver) {
+        return Settings.Secure.getString(resolver, SETTING);
     }
 
-    private synchronized void updateSettings() {
-        try {
-            mParser.setString(Settings.Secure.getString(mResolver,
-                    Settings.Secure.BACKUP_MANAGER_CONSTANTS));
-        } catch (IllegalArgumentException e) {
-            // Failed to parse the settings string. Use defaults.
-            Slog.e(TAG, "Bad backup manager constants: " + e.getMessage());
-        }
-
-        mKeyValueBackupIntervalMilliseconds = mParser.getLong(
-                KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS,
-                DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
-        mKeyValueBackupFuzzMilliseconds = mParser.getLong(KEY_VALUE_BACKUP_FUZZ_MILLISECONDS,
-                DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
-        mKeyValueBackupRequireCharging = mParser.getBoolean(KEY_VALUE_BACKUP_REQUIRE_CHARGING,
-                DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
-        mKeyValueBackupRequiredNetworkType = mParser.getInt(KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE,
-                DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
-        mFullBackupIntervalMilliseconds = mParser.getLong(FULL_BACKUP_INTERVAL_MILLISECONDS,
-                DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
-        mFullBackupRequireCharging = mParser.getBoolean(FULL_BACKUP_REQUIRE_CHARGING,
-                DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
-        mFullBackupRequiredNetworkType = mParser.getInt(FULL_BACKUP_REQUIRED_NETWORK_TYPE,
-                DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
-        String backupFinishedNotificationReceivers = mParser.getString(
-                BACKUP_FINISHED_NOTIFICATION_RECEIVERS,
-                DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS);
+    public synchronized void update(KeyValueListParser parser) {
+        mKeyValueBackupIntervalMilliseconds =
+                parser.getLong(
+                        KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS,
+                        DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+        mKeyValueBackupFuzzMilliseconds =
+                parser.getLong(
+                        KEY_VALUE_BACKUP_FUZZ_MILLISECONDS,
+                        DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+        mKeyValueBackupRequireCharging =
+                parser.getBoolean(
+                        KEY_VALUE_BACKUP_REQUIRE_CHARGING,
+                        DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+        mKeyValueBackupRequiredNetworkType =
+                parser.getInt(
+                        KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE,
+                        DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+        mFullBackupIntervalMilliseconds =
+                parser.getLong(
+                        FULL_BACKUP_INTERVAL_MILLISECONDS,
+                        DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+        mFullBackupRequireCharging =
+                parser.getBoolean(
+                        FULL_BACKUP_REQUIRE_CHARGING, DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+        mFullBackupRequiredNetworkType =
+                parser.getInt(
+                        FULL_BACKUP_REQUIRED_NETWORK_TYPE,
+                        DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+        String backupFinishedNotificationReceivers =
+                parser.getString(
+                        BACKUP_FINISHED_NOTIFICATION_RECEIVERS,
+                        DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS);
         if (backupFinishedNotificationReceivers.isEmpty()) {
             mBackupFinishedNotificationReceivers = new String[] {};
         } else {
@@ -132,40 +152,50 @@
     // a reference of this object.
     public synchronized long getKeyValueBackupIntervalMilliseconds() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getKeyValueBackupIntervalMilliseconds(...) returns "
-                    + mKeyValueBackupIntervalMilliseconds);
+            Slog.v(
+                    TAG,
+                    "getKeyValueBackupIntervalMilliseconds(...) returns "
+                            + mKeyValueBackupIntervalMilliseconds);
         }
         return mKeyValueBackupIntervalMilliseconds;
     }
 
     public synchronized long getKeyValueBackupFuzzMilliseconds() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getKeyValueBackupFuzzMilliseconds(...) returns "
-                    + mKeyValueBackupFuzzMilliseconds);
+            Slog.v(
+                    TAG,
+                    "getKeyValueBackupFuzzMilliseconds(...) returns "
+                            + mKeyValueBackupFuzzMilliseconds);
         }
         return mKeyValueBackupFuzzMilliseconds;
     }
 
     public synchronized boolean getKeyValueBackupRequireCharging() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getKeyValueBackupRequireCharging(...) returns "
-                    + mKeyValueBackupRequireCharging);
+            Slog.v(
+                    TAG,
+                    "getKeyValueBackupRequireCharging(...) returns "
+                            + mKeyValueBackupRequireCharging);
         }
         return mKeyValueBackupRequireCharging;
     }
 
     public synchronized int getKeyValueBackupRequiredNetworkType() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getKeyValueBackupRequiredNetworkType(...) returns "
-                    + mKeyValueBackupRequiredNetworkType);
+            Slog.v(
+                    TAG,
+                    "getKeyValueBackupRequiredNetworkType(...) returns "
+                            + mKeyValueBackupRequiredNetworkType);
         }
         return mKeyValueBackupRequiredNetworkType;
     }
 
     public synchronized long getFullBackupIntervalMilliseconds() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getFullBackupIntervalMilliseconds(...) returns "
-                    + mFullBackupIntervalMilliseconds);
+            Slog.v(
+                    TAG,
+                    "getFullBackupIntervalMilliseconds(...) returns "
+                            + mFullBackupIntervalMilliseconds);
         }
         return mFullBackupIntervalMilliseconds;
     }
@@ -179,19 +209,21 @@
 
     public synchronized int getFullBackupRequiredNetworkType() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getFullBackupRequiredNetworkType(...) returns "
-                    + mFullBackupRequiredNetworkType);
+            Slog.v(
+                    TAG,
+                    "getFullBackupRequiredNetworkType(...) returns "
+                            + mFullBackupRequiredNetworkType);
         }
         return mFullBackupRequiredNetworkType;
     }
 
-    /**
-     * Returns an array of package names that should be notified whenever a backup finishes.
-     */
+    /** Returns an array of package names that should be notified whenever a backup finishes. */
     public synchronized String[] getBackupFinishedNotificationReceivers() {
         if (BackupManagerService.DEBUG_SCHEDULING) {
-            Slog.v(TAG, "getBackupFinishedNotificationReceivers(...) returns "
-                    + TextUtils.join(", ", mBackupFinishedNotificationReceivers));
+            Slog.v(
+                    TAG,
+                    "getBackupFinishedNotificationReceivers(...) returns "
+                            + TextUtils.join(", ", mBackupFinishedNotificationReceivers));
         }
         return mBackupFinishedNotificationReceivers;
     }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 6469091..b6e2dca 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -851,6 +851,10 @@
         mJournal = null;        // will be created on first use
 
         mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
+        // We are observing changes to the constants throughout the lifecycle of BMS. This is
+        // because we reference the constants in multiple areas of BMS, which otherwise would
+        // require frequent starting and stopping.
+        mConstants.start();
 
         // Set up the various sorts of package tracking we do
         mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 15f3a23..ecf80ba 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -610,7 +610,7 @@
     @Override
     public void setUidMode(int code, int uid, int mode) {
         if (Binder.getCallingPid() != Process.myPid()) {
-            mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+            mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
                     Binder.getCallingPid(), Binder.getCallingUid(), null);
         }
         verifyIncomingOp(code);
@@ -714,7 +714,7 @@
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
         if (Binder.getCallingPid() != Process.myPid()) {
-            mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+            mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
                     Binder.getCallingPid(), Binder.getCallingUid(), null);
         }
         verifyIncomingOp(code);
@@ -832,7 +832,7 @@
     public void resetAllModes(int reqUserId, String reqPackageName) {
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
-        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
+        mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
                 callingPid, callingUid, null);
         reqUserId = ActivityManager.handleIncomingUser(callingPid, callingUid, reqUserId,
                 true, true, "resetAllModes", null);
@@ -1087,6 +1087,8 @@
             String[] exceptionPackages) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        mContext.enforcePermission(android.Manifest.permission.MANAGE_APP_OPS_MODES,
+                Binder.getCallingPid(), Binder.getCallingUid(), null);
         synchronized (this) {
             SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
             if (usageRestrictions == null) {
@@ -2330,7 +2332,7 @@
                 }
                 case "write-settings": {
                     shell.mInternal.mContext.enforcePermission(
-                            android.Manifest.permission.UPDATE_APP_OPS_STATS,
+                            android.Manifest.permission.MANAGE_APP_OPS_MODES,
                             Binder.getCallingPid(), Binder.getCallingUid(), null);
                     long token = Binder.clearCallingIdentity();
                     try {
@@ -2346,7 +2348,7 @@
                 }
                 case "read-settings": {
                     shell.mInternal.mContext.enforcePermission(
-                            android.Manifest.permission.UPDATE_APP_OPS_STATS,
+                            android.Manifest.permission.MANAGE_APP_OPS_MODES,
                             Binder.getCallingPid(), Binder.getCallingUid(), null);
                     long token = Binder.clearCallingIdentity();
                     try {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 62e82a0..3896871 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -65,7 +65,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.NoSuchElementException;
 
@@ -164,14 +163,9 @@
 
     private int[] mDataActivity;
 
+    // Connection state of default APN type data (i.e. internet) of phones
     private int[] mDataConnectionState;
 
-    private ArrayList<String>[] mConnectedApns;
-
-    private LinkProperties[] mDataConnectionLinkProperties;
-
-    private NetworkCapabilities[] mDataConnectionNetworkCapabilities;
-
     private Bundle[] mCellLocation;
 
     private int[] mDataConnectionNetworkType;
@@ -323,9 +317,8 @@
         mBatteryStats = BatteryStatsService.getService();
 
         int numPhones = TelephonyManager.getDefault().getPhoneCount();
-        if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
+        if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones);
         mNumPhones = numPhones;
-        mConnectedApns = new ArrayList[numPhones];
         mCallState = new int[numPhones];
         mDataActivity = new int[numPhones];
         mDataConnectionState = new int[numPhones];
@@ -339,8 +332,6 @@
         mMessageWaiting = new boolean[numPhones];
         mCallForwarding = new boolean[numPhones];
         mCellLocation = new Bundle[numPhones];
-        mDataConnectionLinkProperties = new LinkProperties[numPhones];
-        mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
         mCellInfo = new ArrayList<List<CellInfo>>();
         mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
         for (int i = 0; i < numPhones; i++) {
@@ -358,7 +349,6 @@
             mCellLocation[i] = new Bundle();
             mCellInfo.add(i, null);
             mPhysicalChannelConfigs.add(i, null);
-            mConnectedApns[i] = new ArrayList<String>();
         }
 
         // Note that location can be null for non-phone builds like
@@ -1219,36 +1209,12 @@
         int phoneId = SubscriptionManager.getPhoneId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                boolean modified = false;
-                if (state == TelephonyManager.DATA_CONNECTED) {
-                    if (!mConnectedApns[phoneId].contains(apnType)) {
-                        mConnectedApns[phoneId].add(apnType);
-                        if (mDataConnectionState[phoneId] != state) {
-                            mDataConnectionState[phoneId] = state;
-                            modified = true;
-                        }
-                    }
-                } else {
-                    if (mConnectedApns[phoneId].remove(apnType)) {
-                        if (mConnectedApns[phoneId].isEmpty()) {
-                            mDataConnectionState[phoneId] = state;
-                            modified = true;
-                        } else {
-                            // leave mDataConnectionState as is and
-                            // send out the new status for the APN in question.
-                        }
-                    }
-                }
-                mDataConnectionLinkProperties[phoneId] = linkProperties;
-                mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
-                if (mDataConnectionNetworkType[phoneId] != networkType) {
-                    mDataConnectionNetworkType[phoneId] = networkType;
-                    // need to tell registered listeners about the new network type
-                    modified = true;
-                }
-                if (modified) {
-                    String str = "onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
-                            + ", " + mDataConnectionNetworkType[phoneId] + ")";
+                // We only call the callback when the change is for default APN type.
+                if (PhoneConstants.APN_TYPE_DEFAULT.equals(apnType)
+                        && (mDataConnectionState[phoneId] != state
+                        || mDataConnectionNetworkType[phoneId] != networkType)) {
+                    String str = "onDataConnectionStateChanged(" + state
+                            + ", " + networkType + ")";
                     log(str);
                     mLocalLog.log(str);
                     for (Record r : mRecords) {
@@ -1259,15 +1225,16 @@
                                 if (DBG) {
                                     log("Notify data connection state changed on sub: " + subId);
                                 }
-                                r.callback.onDataConnectionStateChanged(
-                                        mDataConnectionState[phoneId],
-                                        mDataConnectionNetworkType[phoneId]);
+                                r.callback.onDataConnectionStateChanged(state, networkType);
                             } catch (RemoteException ex) {
                                 mRemoveList.add(r.binder);
                             }
                         }
                     }
                     handleRemoveListLocked();
+
+                    mDataConnectionState[phoneId] = state;
+                    mDataConnectionNetworkType[phoneId] = networkType;
                 }
                 mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
                         apnType, apn, reason, linkProperties, "");
@@ -1503,14 +1470,10 @@
                 pw.println("mCallForwarding=" + mCallForwarding[i]);
                 pw.println("mDataActivity=" + mDataActivity[i]);
                 pw.println("mDataConnectionState=" + mDataConnectionState[i]);
-                pw.println("mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
-                pw.println("mDataConnectionNetworkCapabilities=" +
-                        mDataConnectionNetworkCapabilities[i]);
                 pw.println("mCellLocation=" + mCellLocation[i]);
                 pw.println("mCellInfo=" + mCellInfo.get(i));
                 pw.decreaseIndent();
             }
-            pw.println("mConnectedApns=" + Arrays.toString(mConnectedApns));
             pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
             pw.println("mPreciseCallState=" + mPreciseCallState);
             pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 26f83f5..eb4e32e 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3390,10 +3390,15 @@
                 return;
             }
 
+            app = r.app;
+            if (app != null && app.debugging) {
+                // The app's being debugged; let it ride
+                return;
+            }
+
             if (DEBUG_BACKGROUND_CHECK) {
                 Slog.i(TAG, "Service foreground-required timeout for " + r);
             }
-            app = r.app;
             r.fgWaiting = false;
             stopServiceLocked(r);
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e38be67..8c49472 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1621,12 +1621,6 @@
             return;
         }
 
-        if (isState(DESTROYED) || (state != DESTROYED && isState(DESTROYING))) {
-            // We cannot move backwards from destroyed and destroying states.
-            throw new IllegalArgumentException("cannot move back states once destroying"
-                    + "current:" + mState + " requested:" + state);
-        }
-
         final ActivityState prev = mState;
         mState = state;
 
@@ -1641,23 +1635,6 @@
         if (parent != null) {
             parent.onActivityStateChanged(this, state, reason);
         }
-
-        if (isState(DESTROYING, DESTROYED)) {
-            makeFinishingLocked();
-
-            // When moving to the destroyed state, immediately destroy the activity in the
-            // associated stack. Most paths for finishing an activity will handle an activity's path
-            // to destroy through mechanisms such as ActivityStackSupervisor#mFinishingActivities.
-            // However, moving to the destroyed state directly (as in the case of an app dying) and
-            // marking it as finished will lead to cleanup steps that will prevent later handling
-            // from happening.
-            if (isState(DESTROYED)) {
-                final ActivityStack stack = getStack();
-                if (stack != null) {
-                    stack.activityDestroyedLocked(this, reason);
-                }
-            }
-        }
     }
 
     ActivityState getState() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 2d7520e..2c4eac0 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2707,9 +2707,12 @@
                     if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                             + lastState + ": " + next);
                     next.setState(lastState, "resumeTopActivityInnerLocked");
-                    if (lastStack != null) {
+
+                    // lastResumedActivity being non-null implies there is a lastStack present.
+                    if (lastResumedActivity != null) {
                         lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                     }
+
                     Slog.i(TAG, "Restarting because process died: " + next);
                     if (!next.hasBeenLaunched) {
                         next.hasBeenLaunched = true;
@@ -3811,14 +3814,6 @@
         final ActivityState prevState = r.getState();
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
 
-        // We are already destroying / have already destroyed the activity. Do not continue to
-        // modify it. Note that we do not use ActivityRecord#finishing here as finishing is not
-        // indicative of destruction (though destruction is indicative of finishing) as finishing
-        // can be delayed below.
-        if (r.isState(DESTROYING, DESTROYED)) {
-            return null;
-        }
-
         r.setState(FINISHING, "finishCurrentActivityLocked");
         final boolean finishingActivityInNonFocusedStack
                 = r.getStack() != mStackSupervisor.getFocusedStack()
@@ -4037,26 +4032,16 @@
      * state to destroy so only the cleanup here is needed.
      *
      * Note: Call before #removeActivityFromHistoryLocked.
-     *
-     * @param r             The {@link ActivityRecord} to cleanup.
-     * @param cleanServices Whether services bound to the {@link ActivityRecord} should also be
-     *                      cleaned up.
-     * @param destroy       Whether the {@link ActivityRecord} should be destroyed.
-     * @param clearProcess  Whether the client process should be cleared.
      */
-    private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean destroy,
-            boolean clearProcess) {
+    private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
         onActivityRemovedFromStack(r);
 
         r.deferRelaunchUntilPaused = false;
         r.frozenBeforeDestroy = false;
 
-        if (destroy) {
+        if (setState) {
             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
             r.setState(DESTROYED, "cleanupActivityLocked");
-        }
-
-        if (clearProcess) {
             if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
             r.app = null;
         }
@@ -4271,7 +4256,7 @@
                         + ", app=" + (r.app != null ? r.app.processName : "(null)"));
 
         if (r.isState(DESTROYING, DESTROYED)) {
-            if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already finishing."
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
                     + "skipping request with reason:" + reason);
             return false;
         }
@@ -4282,8 +4267,7 @@
 
         boolean removedFromHistory = false;
 
-        cleanUpActivityLocked(r, false /* cleanServices */, false /* destroy */,
-                false /*clearProcess*/);
+        cleanUpActivityLocked(r, false, false);
 
         final boolean hadApp = r.app != null;
 
@@ -4380,6 +4364,10 @@
         }
     }
 
+    /**
+     * This method is to only be called from the client via binder when the activity is destroyed
+     * AND finished.
+     */
     final void activityDestroyedLocked(ActivityRecord record, String reason) {
         if (record != null) {
             mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record);
@@ -4389,8 +4377,7 @@
 
         if (isInStackLocked(record) != null) {
             if (record.isState(DESTROYING, DESTROYED)) {
-                cleanUpActivityLocked(record, true /* cleanServices */, false /* destroy */,
-                        false /*clearProcess*/);
+                cleanUpActivityLocked(record, true, false);
                 removeActivityFromHistoryLocked(record, reason);
             }
         }
@@ -4499,8 +4486,7 @@
                             r.icicle = null;
                         }
                     }
-                    cleanUpActivityLocked(r, true /* cleanServices */, remove /* destroy */,
-                            true /*clearProcess*/);
+                    cleanUpActivityLocked(r, true, true);
                     if (remove) {
                         removeActivityFromHistoryLocked(r, "appDied");
                     }
@@ -4511,11 +4497,11 @@
         return hasVisibleActivities;
     }
 
-    private void updateTransitLocked(int transit, ActivityOptions options) {
+    private void updateTransitLocked(int transit, ActivityRecord starting,
+            ActivityOptions options) {
         if (options != null) {
-            ActivityRecord r = topRunningActivityLocked();
-            if (r != null && !r.isState(RESUMED)) {
-                r.updateOptionsLocked(options);
+            if (starting != null && !starting.isState(RESUMED)) {
+                starting.updateOptionsLocked(options);
             } else {
                 ActivityOptions.abort(options);
             }
@@ -4552,8 +4538,9 @@
         }
     }
 
-    final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
-            AppTimeTracker timeTracker, String reason) {
+    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord starting,
+            boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker,
+            String reason) {
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
 
         final ActivityStack topStack = getDisplay().getTopStack();
@@ -4565,7 +4552,7 @@
             if (noAnimation) {
                 ActivityOptions.abort(options);
             } else {
-                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
+                updateTransitLocked(TRANSIT_TASK_TO_FRONT, starting, options);
             }
             return;
         }
@@ -4603,7 +4590,7 @@
             }
             ActivityOptions.abort(options);
         } else {
-            updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
+            updateTransitLocked(TRANSIT_TASK_TO_FRONT, r, options);
         }
         // If a new task is moved to the front, then mark the existing top activity as supporting
         // picture-in-picture while paused only if the task would not be considered an oerlay on top
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 185897a..efc0d7d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2196,7 +2196,7 @@
         }
 
         final ActivityRecord r = task.getTopActivity();
-        currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+        currentStack.moveTaskToFrontLocked(task, r, false /* noAnimation */, options,
                 r == null ? null : r.appTimeTracker, reason);
 
         if (DEBUG_STACK) Slog.d(TAG_STACK,
@@ -3375,7 +3375,8 @@
                     stack.goToSleepIfPossible(false /* shuttingDown */);
                 } else {
                     stack.awakeFromSleepingLocked();
-                    if (isFocusedStack(stack) && !mKeyguardController.isKeyguardLocked()) {
+                    if (isFocusedStack(stack)
+                            && !mKeyguardController.isKeyguardShowing(display.mDisplayId)) {
                         // If the keyguard is unlocked - resume immediately.
                         // It is possible that the display will not be awake at the time we
                         // process the keyguard going away, which can happen before the sleep token
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index bd53eac..2670235 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1815,8 +1815,9 @@
                         // We only want to move to the front, if we aren't going to launch on a
                         // different stack. If we launch on a different stack, we will put the
                         // task on top there.
-                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
-                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
+                        mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity, mNoAnimation,
+                                mOptions, mStartActivity.appTimeTracker,
+                                "bringingFoundTaskToFront");
                         mMovedToFront = true;
                     } else if (launchStack.inSplitScreenWindowingMode()) {
                         if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
@@ -1830,7 +1831,7 @@
                             // We choose to move task to front instead of launching it adjacent
                             // when specific stack was requested explicitly and it appeared to be
                             // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
-                            mTargetStack.moveTaskToFrontLocked(intentTask,
+                            mTargetStack.moveTaskToFrontLocked(intentTask, mStartActivity,
                                     mNoAnimation, mOptions, mStartActivity.appTimeTracker,
                                     "bringToFrontInsteadOfAdjacentLaunch");
                         }
@@ -2059,7 +2060,7 @@
 
         final TaskRecord topTask = mTargetStack.topTask();
         if (topTask != sourceTask && !mAvoidMoveToFront) {
-            mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
+            mTargetStack.moveTaskToFrontLocked(sourceTask, mStartActivity, mNoAnimation, mOptions,
                     mStartActivity.appTimeTracker, "sourceTaskToFront");
         } else if (mDoResume) {
             mTargetStack.moveToFront("sourceStackToFront");
@@ -2125,7 +2126,7 @@
                 && top.userId == mStartActivity.userId) {
             if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                     || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
-                mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
+                mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
                         mStartActivity.appTimeTracker, "inTaskToFront");
                 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                     // We don't need to start a new activity, and the client said not to do
@@ -2138,7 +2139,7 @@
         }
 
         if (!mAddingToTask) {
-            mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
+            mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
                     mStartActivity.appTimeTracker, "inTaskToFront");
             // We don't actually want to have this activity added to the task, so just
             // stop here but still tell the caller that we consumed the intent.
@@ -2158,8 +2159,8 @@
             updateBounds(mInTask, mLaunchParams.mBounds);
         }
 
-        mTargetStack.moveTaskToFrontLocked(
-                mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
+        mTargetStack.moveTaskToFrontLocked(mInTask, mStartActivity, mNoAnimation, mOptions,
+                mStartActivity.appTimeTracker, "inTaskToFront");
 
         addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 4541acd..3db1da5 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -103,7 +103,7 @@
                     .replaceWith("?");
     private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE);
     private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
-    private static final int MAX_LOW_POWER_STATS_SIZE = 512;
+    private static final int MAX_LOW_POWER_STATS_SIZE = 2048;
 
     /**
      * Replaces the information in the given rpmStats with up-to-date information.
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index af99111..ed39329 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -469,6 +469,7 @@
             if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
                 getStatusBarService().showPinningEnterExitToast(false /* entering */);
             }
+            mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
         } catch (RemoteException ex) {
             throw new RuntimeException(ex);
         } finally {
@@ -580,6 +581,7 @@
             if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
                 getStatusBarService().showPinningEnterExitToast(true /* entering */);
             }
+            mWindowManager.onLockTaskStateChanged(lockTaskModeState);
             mLockTaskModeState = lockTaskModeState;
             setStatusBarState(lockTaskModeState, userId);
             setKeyguardState(lockTaskModeState, userId);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index f1b3dfa..3f05ece 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -1238,20 +1238,16 @@
      * list (if any).
      */
     private int findRemoveIndexForAddTask(TaskRecord task) {
-        int recentsCount = mTasks.size();
+        final int recentsCount = mTasks.size();
+        final int taskActivityType = task.getActivityType();
         final Intent intent = task.intent;
         final boolean document = intent != null && intent.isDocument();
         int maxRecents = task.maxRecents - 1;
-        final ActivityStack stack = task.getStack();
         for (int i = 0; i < recentsCount; i++) {
             final TaskRecord tr = mTasks.get(i);
-            final ActivityStack trStack = tr.getStack();
-
+            final int trActivityType = tr.getActivityType();
             if (task != tr) {
-                if (stack != null && trStack != null && stack != trStack) {
-                    continue;
-                }
-                if (task.userId != tr.userId) {
+                if (taskActivityType != trActivityType || task.userId != tr.userId) {
                     continue;
                 }
                 final Intent trIntent = tr.intent;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f577d09..9ef84d2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -727,6 +727,36 @@
             }
         }
 
+        int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
+        if (maxAlarmVolume != -1) {
+            MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
+        }
+
+        int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
+        if (defaultAlarmVolume != -1 &&
+                defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
+            AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
+        } else {
+            // Default is 6 out of 7 (default maximum), so scale accordingly.
+            AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
+                        6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
+        }
+
+        int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
+        if (maxSystemVolume != -1) {
+            MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
+        }
+
+        int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
+        if (defaultSystemVolume != -1 &&
+                defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
+            AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
+        } else {
+            // Default is to use maximum.
+            AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
+                        MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
+        }
+
         sSoundEffectVolumeDb = context.getResources().getInteger(
                 com.android.internal.R.integer.config_soundEffectVolumeDb);
 
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index f1a806b..4f31e53 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -102,9 +102,12 @@
 
 
     /**
-     * There are only 2 possible callbacks.
+     * There are only 3 possible callbacks.
      *
-     * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY].
+     * mNetdEventCallbackList[CALLBACK_CALLER_CONNECTIVITY_SERVICE]
+     * Callback registered/unregistered by ConnectivityService.
+     *
+     * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY]
      * Callback registered/unregistered when logging is being enabled/disabled in DPM
      * by the device owner. It's DevicePolicyManager's responsibility to ensure that.
      *
@@ -113,6 +116,7 @@
      */
     @GuardedBy("this")
     private static final int[] ALLOWED_CALLBACK_TYPES = {
+        INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
         INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY,
         INetdEventCallback.CALLBACK_CALLER_NETWORK_WATCHLIST
     };
@@ -212,6 +216,19 @@
     @Override
     // Called concurrently by multiple binder threads.
     // This method must not block or perform long-running operations.
+    public synchronized void onPrivateDnsValidationEvent(int netId,
+            String ipAddress, String hostname, boolean validated)
+            throws RemoteException {
+        for (INetdEventCallback callback : mNetdEventCallbackList) {
+            if (callback != null) {
+                callback.onPrivateDnsValidationEvent(netId, ipAddress, hostname, validated);
+            }
+        }
+    }
+
+    @Override
+    // Called concurrently by multiple binder threads.
+    // This method must not block or perform long-running operations.
     public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr,
             int port, int uid) throws RemoteException {
         long timestamp = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 3a8e291..2405925 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -45,7 +45,7 @@
     private Rect mCurrentDisplayRect;
 
     // The display device owns its surface, but it should only set it
-    // within a transaction from performTraversalInTransactionLocked.
+    // within a transaction from performTraversalLocked.
     private Surface mCurrentSurface;
 
     // DEBUG STATE: Last device info which was written to the log, or null if none.
@@ -122,7 +122,7 @@
     /**
      * Gives the display device a chance to update its properties while in a transaction.
      */
-    public void performTraversalInTransactionLocked() {
+    public void performTraversalLocked(SurfaceControl.Transaction t) {
     }
 
     /**
@@ -140,7 +140,7 @@
     /**
      * Sets the mode, if supported.
      */
-    public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) {
+    public void requestDisplayModesLocked(int colorMode, int modeId) {
     }
 
     public void onOverlayChangedLocked() {
@@ -149,10 +149,10 @@
     /**
      * Sets the display layer stack while in a transaction.
      */
-    public final void setLayerStackInTransactionLocked(int layerStack) {
+    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
-            SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack);
+            t.setDisplayLayerStack(mDisplayToken, layerStack);
         }
     }
 
@@ -166,7 +166,7 @@
      *            mapped to. displayRect is specified post-orientation, that is
      *            it uses the orientation seen by the end-user
      */
-    public final void setProjectionInTransactionLocked(int orientation,
+    public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation,
             Rect layerStackRect, Rect displayRect) {
         if (mCurrentOrientation != orientation
                 || mCurrentLayerStackRect == null
@@ -185,7 +185,7 @@
             }
             mCurrentDisplayRect.set(displayRect);
 
-            SurfaceControl.setDisplayProjection(mDisplayToken,
+            t.setDisplayProjection(mDisplayToken,
                     orientation, layerStackRect, displayRect);
         }
     }
@@ -193,10 +193,10 @@
     /**
      * Sets the display surface while in a transaction.
      */
-    public final void setSurfaceInTransactionLocked(Surface surface) {
+    public final void setSurfaceLocked(SurfaceControl.Transaction t, Surface surface) {
         if (mCurrentSurface != surface) {
             mCurrentSurface = surface;
-            SurfaceControl.setDisplaySurface(mDisplayToken, surface);
+            t.setDisplaySurface(mDisplayToken, surface);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a5c1fe2..9861ea7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -74,6 +74,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import com.android.internal.util.Preconditions;
 import com.android.server.AnimationThread;
@@ -457,14 +458,14 @@
     }
 
     @VisibleForTesting
-    void performTraversalInTransactionFromWindowManagerInternal() {
+    void performTraversalInternal(SurfaceControl.Transaction t) {
         synchronized (mSyncRoot) {
             if (!mPendingTraversal) {
                 return;
             }
             mPendingTraversal = false;
 
-            performTraversalInTransactionLocked();
+            performTraversalLocked(t);
         }
 
         // List is self-synchronized copy-on-write.
@@ -1056,7 +1057,7 @@
         return changed;
     }
 
-    private void performTraversalInTransactionLocked() {
+    private void performTraversalLocked(SurfaceControl.Transaction t) {
         // Clear all viewports before configuring displays so that we can keep
         // track of which ones we have configured.
         clearViewportsLocked();
@@ -1065,8 +1066,8 @@
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            configureDisplayInTransactionLocked(device);
-            device.performTraversalInTransactionLocked();
+            configureDisplayLocked(t, device);
+            device.performTraversalLocked(t);
         }
 
         // Tell the input system about these new viewports.
@@ -1150,7 +1151,7 @@
         mVirtualTouchViewports.clear();
     }
 
-    private void configureDisplayInTransactionLocked(DisplayDevice device) {
+    private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
 
@@ -1175,7 +1176,7 @@
                     + device.getDisplayDeviceInfoLocked());
             return;
         }
-        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
+        display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
 
         // Update the viewports if needed.
         if (!mDefaultViewport.valid
@@ -1233,7 +1234,7 @@
         mHandler.sendMessage(msg);
     }
 
-    // Requests that performTraversalsInTransactionFromWindowManager be called at a
+    // Requests that performTraversals be called at a
     // later time to apply changes to surfaces and displays.
     private void scheduleTraversalLocked(boolean inTraversal) {
         if (!mPendingTraversal && mWindowManagerInternal != null) {
@@ -2031,8 +2032,8 @@
         }
 
         @Override
-        public void performTraversalInTransactionFromWindowManager() {
-            performTraversalInTransactionFromWindowManagerInternal();
+        public void performTraversal(SurfaceControl.Transaction t) {
+            performTraversalInternal(t);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 0d8ec6d..5ca9abc 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -584,10 +584,9 @@
         }
 
         @Override
-        public void requestDisplayModesInTransactionLocked(
-                int colorMode, int modeId) {
-            if (requestModeInTransactionLocked(modeId) ||
-                    requestColorModeInTransactionLocked(colorMode)) {
+        public void requestDisplayModesLocked(int colorMode, int modeId) {
+            if (requestModeLocked(modeId) ||
+                    requestColorModeLocked(colorMode)) {
                 updateDeviceInfoLocked();
             }
         }
@@ -597,7 +596,7 @@
             updateDeviceInfoLocked();
         }
 
-        public boolean requestModeInTransactionLocked(int modeId) {
+        public boolean requestModeLocked(int modeId) {
             if (modeId == 0) {
                 modeId = mDefaultModeId;
             } else if (mSupportedModes.indexOfKey(modeId) < 0) {
@@ -623,7 +622,7 @@
             return true;
         }
 
-        public boolean requestColorModeInTransactionLocked(int colorMode) {
+        public boolean requestColorModeLocked(int colorMode) {
             if (mActiveColorMode == colorMode) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index e582fdf..23ee56b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -21,6 +21,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -304,17 +305,18 @@
      * @param device The display device to modify.
      * @param isBlanked True if the device is being blanked.
      */
-    public void configureDisplayInTransactionLocked(DisplayDevice device,
+    public void configureDisplayLocked(SurfaceControl.Transaction t,
+            DisplayDevice device,
             boolean isBlanked) {
         // Set the layer stack.
-        device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
 
         // Set the color mode and mode.
         if (device == mPrimaryDisplayDevice) {
-            device.requestDisplayModesInTransactionLocked(
+            device.requestDisplayModesLocked(
                     mRequestedColorMode, mRequestedModeId);
         } else {
-            device.requestDisplayModesInTransactionLocked(0, 0);  // Revert to default.
+            device.requestDisplayModesLocked(0, 0);  // Revert to default.
         }
 
         // Only grab the display info now as it may have been changed based on the requests above.
@@ -377,7 +379,7 @@
         mTempDisplayRect.right += mDisplayOffsetX;
         mTempDisplayRect.top += mDisplayOffsetY;
         mTempDisplayRect.bottom += mDisplayOffsetY;
-        device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
+        device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS
index 8361421..98e3299 100644
--- a/services/core/java/com/android/server/display/OWNERS
+++ b/services/core/java/com/android/server/display/OWNERS
@@ -1,3 +1,5 @@
 michaelwr@google.com
+hackbod@google.com
+ogunwale@google.com
 
-per-file ColorDisplayService.java=christyfranks@google.com
\ No newline at end of file
+per-file ColorDisplayService.java=christyfranks@google.com
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 27327d4..e65637f 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -271,12 +271,12 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if (mSurfaceTexture != null) {
                 if (mSurface == null) {
                     mSurface = new Surface(mSurfaceTexture);
                 }
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
         }
 
@@ -315,7 +315,7 @@
         }
 
         @Override
-        public void requestDisplayModesInTransactionLocked(int color, int id) {
+        public void requestDisplayModesLocked(int color, int id) {
             int index = -1;
             if (id == 0) {
                 // Use the default.
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index f86d576..6111c23 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -269,12 +269,12 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if ((mPendingChanges & PENDING_RESIZE) != 0) {
-                SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
+                t.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
             }
             if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) {
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
             mPendingChanges = 0;
         }
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 3293379..e8d6ad4 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -620,9 +620,9 @@
         }
 
         @Override
-        public void performTraversalInTransactionLocked() {
+        public void performTraversalLocked(SurfaceControl.Transaction t) {
             if (mSurface != null) {
-                setSurfaceInTransactionLocked(mSurface);
+                setSurfaceLocked(t, mSurface);
             }
         }
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 8efce86..5bfdf41 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -45,6 +45,7 @@
 import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertPath;
+import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -148,6 +149,11 @@
             mPlatformKeyManager.invalidatePlatformKey(mUserId, generation);
             return;
         }
+        if (isCustomLockScreen()) {
+            Log.w(TAG, "Unsupported credential type " + mCredentialType + "for user " + mUserId);
+            mRecoverableKeyStoreDb.invalidateKeysForUserIdOnCustomScreenLock(mUserId);
+            return;
+        }
 
         List<Integer> recoveryAgents = mRecoverableKeyStoreDb.getRecoveryAgents(mUserId);
         for (int uid : recoveryAgents) {
@@ -158,6 +164,12 @@
         }
     }
 
+    private boolean isCustomLockScreen() {
+        return mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_NONE
+            && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PATTERN
+            && mCredentialType != LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
+    }
+
     private void syncKeysForAgent(int recoveryAgentUid) {
         boolean recreateCurrentVersion = false;
         if (!shoudCreateSnapshot(recoveryAgentUid)) {
@@ -284,17 +296,23 @@
         // If application keys are not updated, snapshot will not be created on next unlock.
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder()
+        KeyChainSnapshot.Builder keyChainSnapshotBuilder = new KeyChainSnapshot.Builder()
                 .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion))
                 .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
                 .setCounterId(counterId)
                 .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
-                .setTrustedHardwareCertPath(certPath)
                 .setServerParams(vaultHandle)
                 .setKeyChainProtectionParams(metadataList)
                 .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
-                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
-                .build());
+                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey);
+        try {
+            keyChainSnapshotBuilder.setTrustedHardwareCertPath(certPath);
+        } catch(CertificateException e) {
+            // Should not happen, as it's just deserialized from bytes stored in the db
+            Log.wtf(TAG, "Cannot serialize CertPath when calling setTrustedHardwareCertPath", e);
+            return;
+        }
+        mRecoverySnapshotStorage.put(recoveryAgentUid, keyChainSnapshotBuilder.build());
 
         mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid);
     }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index 89ddb6c..2676ee8 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -320,6 +320,20 @@
     }
 
     /**
+     * Updates status of old keys to {@code RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE}.
+     */
+    public void invalidateKeysForUserIdOnCustomScreenLock(int userId) {
+        SQLiteDatabase db = mKeyStoreDbHelper.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS,
+            RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE);
+        String selection =
+            KeysEntry.COLUMN_NAME_USER_ID + " = ?";
+        db.update(KeysEntry.TABLE_NAME, values, selection,
+            new String[] {String.valueOf(userId)});
+    }
+
+    /**
      * Returns the generation ID associated with the platform key of the user with {@code userId}.
      */
     public int getPlatformKeyGenerationId(int userId) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index aa1f7d95..e862530 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -874,7 +874,14 @@
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
                 applyRestrictions(muteMedia || muteEverything, usage);
             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
-                applyRestrictions(muteSystem || muteEverything, usage);
+                if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+                    // normally DND will only restrict touch sounds, not haptic feedback/vibrations
+                    applyRestrictions(muteSystem || muteEverything, usage,
+                            AppOpsManager.OP_PLAY_AUDIO);
+                    applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
+                } else {
+                    applyRestrictions(muteSystem || muteEverything, usage);
+                }
             } else {
                 applyRestrictions(muteEverything, usage);
             }
@@ -883,18 +890,31 @@
 
 
     @VisibleForTesting
-    protected void applyRestrictions(boolean mute, int usage) {
+    protected void applyRestrictions(boolean mute, int usage, int code) {
         final String[] exceptionPackages = null; // none (for now)
 
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
-                mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
-                mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
+        // Only do this if we are executing within the system process...  otherwise
+        // we are running as test code, so don't have access to the protected call.
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mAppOps.setRestriction(code, usage,
+                        mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                        exceptionPackages);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
     }
 
     @VisibleForTesting
+    protected void applyRestrictions(boolean mute, int usage) {
+        applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
+        applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
+    }
+
+
+    @VisibleForTesting
     protected void applyZenToRingerMode() {
         if (mAudioManager == null) return;
         // force the ringer mode into compliance
@@ -1183,15 +1203,21 @@
         final Bundle extras = new Bundle();
         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                 mContext.getResources().getString(R.string.global_action_settings));
-        return new Notification.Builder(mContext, SystemNotificationChannels.SYSTEM_CHANGES)
+        int title = R.string.zen_upgrade_notification_title;
+        int content = R.string.zen_upgrade_notification_content;
+        if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
+                getNotificationPolicy().suppressedVisualEffects)) {
+            title = R.string.zen_upgrade_notification_visd_title;
+            content = R.string.zen_upgrade_notification_visd_content;
+        }
+        return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
                 .setSmallIcon(R.drawable.ic_settings_24dp)
-                .setContentTitle(mContext.getResources().getString(
-                        R.string.zen_upgrade_notification_title))
-                .setContentText(mContext.getResources().getString(
-                        R.string.zen_upgrade_notification_content))
+                .setContentTitle(mContext.getResources().getString(title))
+                .setContentText(mContext.getResources().getString(content))
                 .setAutoCancel(true)
                 .setLocalOnly(true)
                 .addExtras(extras)
+                .setStyle(new Notification.BigTextStyle())
                 .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0, null))
                 .build();
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 707184f..1082478 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2877,7 +2877,8 @@
                             rescanFlags =
                                     scanFlags
                                     | SCAN_AS_SYSTEM;
-                        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)) {
+                        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)
+                                || FileUtils.contains(privilegedOdmAppDir, scanFile)) {
                             reparseFlags =
                                     mDefParseFlags |
                                     PackageParser.PARSE_IS_SYSTEM_DIR;
@@ -2886,7 +2887,8 @@
                                     | SCAN_AS_SYSTEM
                                     | SCAN_AS_VENDOR
                                     | SCAN_AS_PRIVILEGED;
-                        } else if (FileUtils.contains(vendorAppDir, scanFile)) {
+                        } else if (FileUtils.contains(vendorAppDir, scanFile)
+                                || FileUtils.contains(odmAppDir, scanFile)) {
                             reparseFlags =
                                     mDefParseFlags |
                                     PackageParser.PARSE_IS_SYSTEM_DIR;
@@ -11788,6 +11790,8 @@
             codeRoot = Environment.getOemDirectory();
         } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
             codeRoot = Environment.getVendorDirectory();
+        } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
+            codeRoot = Environment.getOdmDirectory();
         } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
             codeRoot = Environment.getProductDirectory();
         } else {
@@ -18217,9 +18221,11 @@
         try {
             final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
             final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+            final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
             final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
             return path.startsWith(privilegedAppDir.getCanonicalPath())
                     || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
+                    || path.startsWith(privilegedOdmAppDir.getCanonicalPath())
                     || path.startsWith(privilegedProductAppDir.getCanonicalPath());
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
@@ -18238,7 +18244,8 @@
 
     static boolean locationIsVendor(String path) {
         try {
-            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath());
+            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath())
+                    || path.startsWith(Environment.getOdmDirectory().getCanonicalPath());
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -23840,6 +23847,15 @@
         }
 
         @Override
+        public boolean canAccessComponent(int callingUid, ComponentName component, int userId) {
+            synchronized (mPackages) {
+                final PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+                return !PackageManagerService.this.filterAppAccessLPr(
+                        ps, callingUid, component, TYPE_UNKNOWN, userId);
+            }
+        }
+
+        @Override
         public boolean hasInstantApplicationMetadata(String packageName, int userId) {
             synchronized (mPackages) {
                 return mInstantAppRegistry.hasInstantApplicationMetadataLPr(packageName, userId);
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 4abcce1..bf85f30 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1240,6 +1240,10 @@
         if (dir.isDirectory() && dir.canRead()) {
             Collections.addAll(ret, dir.listFiles());
         }
+        dir = new File(Environment.getOdmDirectory(), "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
+        }
         dir = new File(Environment.getProductDirectory(), "etc/default-permissions");
         if (dir.isDirectory() && dir.canRead()) {
             Collections.addAll(ret, dir.listFiles());
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index c6ec287..4aa2446 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -16,6 +16,9 @@
 
 package com.android.server.policy;
 
+import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
+import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+
 import android.animation.ArgbEvaluator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
@@ -78,6 +81,7 @@
     // Local copy of vr mode enabled state, to avoid calling into VrManager with
     // the lock held.
     boolean mVrModeEnabled = false;
+    private int mLockTaskState = LOCK_TASK_MODE_NONE;
 
     public ImmersiveModeConfirmation(Context context) {
         mContext = ActivityThread.currentActivityThread().getSystemUiContext();
@@ -148,7 +152,8 @@
                     && userSetupComplete
                     && !mVrModeEnabled
                     && !navBarEmpty
-                    && !UserManager.isDeviceInDemoMode(mContext)) {
+                    && !UserManager.isDeviceInDemoMode(mContext)
+                    && (mLockTaskState != LOCK_TASK_MODE_LOCKED)) {
                 mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
             }
         } else {
@@ -401,4 +406,8 @@
             }
         }
     };
+
+    void onLockTaskModeChangedLw(int lockTaskState) {
+        mLockTaskState = lockTaskState;
+    }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2d4438d..3cd79e1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1456,6 +1456,9 @@
                     + "already in the process of turning the screen on.");
             return;
         }
+        Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
+                + " count=" + count + " beganFromNonInteractive=" + mBeganFromNonInteractive +
+                " mShortPressOnPowerBehavior=" + mShortPressOnPowerBehavior);
 
         if (count == 2) {
             powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
@@ -1755,7 +1758,6 @@
     }
 
     void showGlobalActionsInternal() {
-        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
         if (mGlobalActions == null) {
             mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
         }
@@ -8809,4 +8811,9 @@
                 return Integer.toString(behavior);
         }
     }
+
+    @Override
+    public void onLockTaskStateChangedLw(int lockTaskState) {
+        mImmersiveModeConfirmation.onLockTaskModeChangedLw(lockTaskState);
+    }
 }
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 8ec8c5b..b0d5e1a 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -66,6 +66,7 @@
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
@@ -1731,4 +1732,15 @@
      * on the next user activity.
      */
     public void requestUserActivityNotification();
+
+    /**
+     * Called when the state of lock task mode changes. This should be used to disable immersive
+     * mode confirmation.
+     *
+     * @param lockTaskState the new lock task mode state. One of
+     *                      {@link ActivityManager#LOCK_TASK_MODE_NONE},
+     *                      {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+     *                      {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
+     */
+    void onLockTaskStateChangedLw(int lockTaskState);
 }
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b729b6a..285532a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -720,9 +720,12 @@
     private void playChargingStartedSound() {
         final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
+        final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+                == Settings.Global.ZEN_MODE_OFF;
         final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.CHARGING_STARTED_SOUND);
-        if (enabled && soundPath != null) {
+        if (enabled && dndOff && soundPath != null) {
             final Uri soundUri = Uri.parse("file://" + soundPath);
             if (soundUri != null) {
                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
index 6bacdfd..8af76a1 100644
--- a/services/core/java/com/android/server/search/Searchables.java
+++ b/services/core/java/com/android/server/search/Searchables.java
@@ -26,14 +26,18 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.server.LocalServices;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -119,7 +123,15 @@
         SearchableInfo result;
         synchronized (this) {
             result = mSearchablesMap.get(activity);
-            if (result != null) return result;
+            if (result != null) {
+                final PackageManagerInternal pm =
+                        LocalServices.getService(PackageManagerInternal.class);
+                if (pm.canAccessComponent(Binder.getCallingUid(), result.getSearchActivity(),
+                        UserHandle.getCallingUserId())) {
+                    return result;
+                }
+                return null;
+            }
         }
 
         // Step 2.  See if the current activity references a searchable.
@@ -170,8 +182,16 @@
                 result = mSearchablesMap.get(referredActivity);
                 if (result != null) {
                     mSearchablesMap.put(activity, result);
+                }
+            }
+            if (result != null) {
+                final PackageManagerInternal pm =
+                        LocalServices.getService(PackageManagerInternal.class);
+                if (pm.canAccessComponent(Binder.getCallingUid(), result.getSearchActivity(),
+                        UserHandle.getCallingUserId())) {
                     return result;
                 }
+                return null;
             }
         }
 
@@ -410,7 +430,7 @@
             activities =
                     mPm.queryIntentActivities(intent,
                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags, mUserId).getList();
+                    flags | PackageManager.MATCH_INSTANT, mUserId).getList();
         } catch (RemoteException re) {
             // Local call
         }
@@ -421,36 +441,82 @@
      * Returns the list of searchable activities.
      */
     public synchronized ArrayList<SearchableInfo> getSearchablesList() {
-        ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList);
-        return result;
+        return createFilterdSearchableInfoList(mSearchablesList);
     }
 
     /**
      * Returns a list of the searchable activities that can be included in global search.
      */
     public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() {
-        return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList);
+        return createFilterdSearchableInfoList(mSearchablesInGlobalSearchList);
     }
 
     /**
      * Returns a list of activities that handle the global search intent.
      */
     public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() {
-        return new ArrayList<ResolveInfo>(mGlobalSearchActivities);
+        return createFilterdResolveInfoList(mGlobalSearchActivities);
+    }
+
+    private ArrayList<SearchableInfo> createFilterdSearchableInfoList(List<SearchableInfo> list) {
+        if (list == null) {
+            return null;
+        }
+        final ArrayList<SearchableInfo> resultList = new ArrayList<>(list.size());
+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getCallingUserId();
+        for (SearchableInfo info : list) {
+            if (pm.canAccessComponent(callingUid, info.getSearchActivity(), callingUserId)) {
+                resultList.add(info);
+            }
+        }
+        return resultList;
+    }
+
+    private ArrayList<ResolveInfo> createFilterdResolveInfoList(List<ResolveInfo> list) {
+        if (list == null) {
+            return null;
+        }
+        final ArrayList<ResolveInfo> resultList = new ArrayList<>(list.size());
+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getCallingUserId();
+        for (ResolveInfo info : list) {
+            if (pm.canAccessComponent(
+                    callingUid, info.activityInfo.getComponentName(), callingUserId)) {
+                resultList.add(info);
+            }
+        }
+        return resultList;
     }
 
     /**
      * Gets the name of the global search activity.
      */
     public synchronized ComponentName getGlobalSearchActivity() {
-        return mCurrentGlobalSearchActivity;
+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (mCurrentGlobalSearchActivity != null
+                && pm.canAccessComponent(callingUid, mCurrentGlobalSearchActivity, callingUserId)) {
+            return mCurrentGlobalSearchActivity;
+        }
+        return null;
     }
 
     /**
      * Gets the name of the web search activity.
      */
     public synchronized ComponentName getWebSearchActivity() {
-        return mWebSearchActivity;
+        final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (mWebSearchActivity != null
+                && pm.canAccessComponent(callingUid, mWebSearchActivity, callingUserId)) {
+            return mWebSearchActivity;
+        }
+        return null;
     }
 
     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/services/core/java/com/android/server/slice/PinnedSliceState.java b/services/core/java/com/android/server/slice/PinnedSliceState.java
index f9a4ea2..4e7fb96 100644
--- a/services/core/java/com/android/server/slice/PinnedSliceState.java
+++ b/services/core/java/com/android/server/slice/PinnedSliceState.java
@@ -14,9 +14,6 @@
 
 package com.android.server.slice;
 
-import static android.app.slice.SliceManager.PERMISSION_GRANTED;
-
-import android.app.slice.Slice;
 import android.app.slice.SliceProvider;
 import android.app.slice.SliceSpec;
 import android.content.ContentProviderClient;
@@ -33,7 +30,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -54,18 +50,24 @@
     private final ArraySet<String> mPinnedPkgs = new ArraySet<>();
     @GuardedBy("mLock")
     private final ArrayMap<IBinder, ListenerInfo> mListeners = new ArrayMap<>();
+    private final String mPkg;
     @GuardedBy("mLock")
     private SliceSpec[] mSupportedSpecs = null;
 
     private final DeathRecipient mDeathRecipient = this::handleRecheckListeners;
     private boolean mSlicePinned;
 
-    public PinnedSliceState(SliceManagerService service, Uri uri) {
+    public PinnedSliceState(SliceManagerService service, Uri uri, String pkg) {
         mService = service;
         mUri = uri;
+        mPkg = pkg;
         mLock = mService.getLock();
     }
 
+    public String getPkg() {
+        return mPkg;
+    }
+
     public SliceSpec[] getSpecs() {
         return mSupportedSpecs;
     }
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 51e4709..a7dfd35 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -149,11 +149,25 @@
 
     ///  ----- ISliceManager stuff -----
     @Override
+    public Uri[] getPinnedSlices(String pkg) {
+        verifyCaller(pkg);
+        ArrayList<Uri> ret = new ArrayList<>();
+        synchronized (mLock) {
+            for (PinnedSliceState state : mPinnedSlicesByUri.values()) {
+                if (Objects.equals(pkg, state.getPkg())) {
+                    ret.add(state.getUri());
+                }
+            }
+        }
+        return ret.toArray(new Uri[ret.size()]);
+    }
+
+    @Override
     public void pinSlice(String pkg, Uri uri, SliceSpec[] specs, IBinder token) throws RemoteException {
         verifyCaller(pkg);
         enforceAccess(pkg, uri);
         uri = maybeAddUserId(uri, Binder.getCallingUserHandle().getIdentifier());
-        getOrCreatePinnedSlice(uri).pin(pkg, specs, token);
+        getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token);
     }
 
     @Override
@@ -302,11 +316,11 @@
         }
     }
 
-    private PinnedSliceState getOrCreatePinnedSlice(Uri uri) {
+    private PinnedSliceState getOrCreatePinnedSlice(Uri uri, String pkg) {
         synchronized (mLock) {
             PinnedSliceState manager = mPinnedSlicesByUri.get(uri);
             if (manager == null) {
-                manager = createPinnedSlice(uri);
+                manager = createPinnedSlice(uri, pkg);
                 mPinnedSlicesByUri.put(uri, manager);
             }
             return manager;
@@ -314,8 +328,8 @@
     }
 
     @VisibleForTesting
-    protected PinnedSliceState createPinnedSlice(Uri uri) {
-        return new PinnedSliceState(this, uri);
+    protected PinnedSliceState createPinnedSlice(Uri uri, String pkg) {
+        return new PinnedSliceState(this, uri, pkg);
     }
 
     public Object getLock() {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 40f772a..1170148 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -379,6 +379,8 @@
 
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
                 wtoken.mAppStopped = false;
+
+                mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
             }
 
             // If we are preparing an app transition, then delay changing
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 2672337..fef615d 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -187,6 +187,7 @@
     StartingSurface startingSurface;
     boolean startingDisplayed;
     boolean startingMoved;
+
     // True if the hidden state of this token was forced to false due to a transferred starting
     // window.
     private boolean mHiddenSetFromTransferredStartingWindow;
@@ -1091,7 +1092,7 @@
                 mService.registerAppFreezeListener(this);
                 mService.mAppsFreezingScreen++;
                 if (mService.mAppsFreezingScreen == 1) {
-                    mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
+                    mService.startFreezingDisplayLocked(0, 0, getDisplayContent());
                     mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
                 }
@@ -1136,6 +1137,25 @@
         stopFreezingScreen(true, true);
     }
 
+    /**
+     * Tries to transfer the starting window from a token that's above ourselves in the task but
+     * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
+     * activity M in the same task. Now, when reopening the task, T starts on top of M but then
+     * immediately finishes after, so we have to transfer T to M.
+     */
+    void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
+        final Task task = getTask();
+        for (int i = task.mChildren.size() - 1; i >= 0; i--) {
+            final AppWindowToken fromToken = task.mChildren.get(i);
+            if (fromToken == this) {
+                return;
+            }
+            if (fromToken.hiddenRequested && transferStartingWindow(fromToken.token)) {
+                return;
+            }
+        }
+    }
+
     boolean transferStartingWindow(IBinder transferFrom) {
         final AppWindowToken fromToken = getDisplayContent().getAppWindowToken(transferFrom);
         if (fromToken == null) {
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index f19cd0f..1977e12 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -41,7 +41,7 @@
         final int layer;
         final SurfaceControl surface;
 
-        BlackSurface(int layer,
+        BlackSurface(SurfaceControl.Transaction transaction, int layer,
                 int l, int t, int r, int b, DisplayContent dc) throws OutOfResourcesException {
             left = l;
             top = t;
@@ -56,24 +56,24 @@
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
 
-            surface.setAlpha(1);
-            surface.setLayer(layer);
-            surface.show();
+            transaction.setAlpha(surface, 1);
+            transaction.setLayer(surface, layer);
+            transaction.show(surface);
             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
                             "  BLACK " + surface + ": CREATE layer=" + layer);
         }
 
-        void setAlpha(float alpha) {
-            surface.setAlpha(alpha);
+        void setAlpha(SurfaceControl.Transaction t, float alpha) {
+            t.setAlpha(surface, alpha);
         }
 
-        void setMatrix(Matrix matrix) {
+        void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
             mTmpMatrix.setTranslate(left, top);
             mTmpMatrix.postConcat(matrix);
             mTmpMatrix.getValues(mTmpFloats);
-            surface.setPosition(mTmpFloats[Matrix.MTRANS_X],
+            t.setPosition(surface, mTmpFloats[Matrix.MTRANS_X],
                     mTmpFloats[Matrix.MTRANS_Y]);
-            surface.setMatrix(
+            t.setMatrix(surface,
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
             if (false) {
@@ -87,8 +87,8 @@
             }
         }
 
-        void clearMatrix() {
-            surface.setMatrix(1, 0, 0, 1);
+        void clearMatrix(SurfaceControl.Transaction t) {
+            t.setMatrix(surface, 1, 0, 0, 1);
         }
     }
 
@@ -113,7 +113,8 @@
         }
     }
 
-    public BlackFrame(Rect outer, Rect inner, int layer, DisplayContent dc,
+    public BlackFrame(SurfaceControl.Transaction t,
+            Rect outer, Rect inner, int layer, DisplayContent dc,
             boolean forceDefaultOrientation) throws OutOfResourcesException {
         boolean success = false;
 
@@ -125,19 +126,19 @@
         mInnerRect = new Rect(inner);
         try {
             if (outer.top < inner.top) {
-                mBlackSurfaces[0] = new BlackSurface(layer,
+                mBlackSurfaces[0] = new BlackSurface(t, layer,
                         outer.left, outer.top, inner.right, inner.top, dc);
             }
             if (outer.left < inner.left) {
-                mBlackSurfaces[1] = new BlackSurface(layer,
+                mBlackSurfaces[1] = new BlackSurface(t, layer,
                         outer.left, inner.top, inner.left, outer.bottom, dc);
             }
             if (outer.bottom > inner.bottom) {
-                mBlackSurfaces[2] = new BlackSurface(layer,
+                mBlackSurfaces[2] = new BlackSurface(t, layer,
                         inner.left, inner.bottom, outer.right, outer.bottom, dc);
             }
             if (outer.right > inner.right) {
-                mBlackSurfaces[3] = new BlackSurface(layer,
+                mBlackSurfaces[3] = new BlackSurface(t, layer,
                         inner.right, outer.top, outer.right, inner.bottom, dc);
             }
             success = true;
@@ -161,36 +162,36 @@
         }
     }
 
-    public void hide() {
+    public void hide(SurfaceControl.Transaction t) {
         if (mBlackSurfaces != null) {
             for (int i=0; i<mBlackSurfaces.length; i++) {
                 if (mBlackSurfaces[i] != null) {
-                    mBlackSurfaces[i].surface.hide();
+                    t.hide(mBlackSurfaces[i].surface);
                 }
             }
         }
     }
 
-    public void setAlpha(float alpha) {
+    public void setAlpha(SurfaceControl.Transaction t, float alpha) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].setAlpha(alpha);
+                mBlackSurfaces[i].setAlpha(t, alpha);
             }
         }
     }
 
-    public void setMatrix(Matrix matrix) {
+    public void setMatrix(SurfaceControl.Transaction t, Matrix matrix) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].setMatrix(matrix);
+                mBlackSurfaces[i].setMatrix(t, matrix);
             }
         }
     }
 
-    public void clearMatrix() {
+    public void clearMatrix(SurfaceControl.Transaction t) {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
-                mBlackSurfaces[i].clearMatrix();
+                mBlackSurfaces[i].clearMatrix(t);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2dce913..59babcf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -258,7 +258,7 @@
      * Current rotation of the display.
      * Constants as per {@link android.view.Surface.Rotation}.
      *
-     * @see #updateRotationUnchecked(boolean)
+     * @see #updateRotationUnchecked()
      */
     private int mRotation = 0;
 
@@ -274,7 +274,7 @@
      * Flag indicating that the application is receiving an orientation that has different metrics
      * than it expected. E.g. Portrait instead of Landscape.
      *
-     * @see #updateRotationUnchecked(boolean)
+     * @see #updateRotationUnchecked()
      */
     private boolean mAltOrientation = false;
 
@@ -926,7 +926,7 @@
      * Returns true if the rotation has been changed.  In this case YOU MUST CALL
      * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
      */
-    boolean updateRotationUnchecked(boolean inTransaction) {
+    boolean updateRotationUnchecked() {
         if (mService.mDeferredRotationPauseCount > 0) {
             // Rotation updates have been paused temporarily.  Defer the update until
             // updates have been resumed.
@@ -1030,7 +1030,7 @@
         mService.mPolicy.selectRotationAnimationLw(anim);
 
         if (!rotateSeamlessly) {
-            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
+            mService.startFreezingDisplayLocked(anim[0], anim[1], this);
             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
             screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
                     mDisplayId);
@@ -1041,9 +1041,7 @@
             // to their rotated state independently and without a freeze required.
             screenRotationAnimation = null;
 
-            // We have to reset this in case a window was removed before it
-            // finished seamless rotation.
-            mService.mSeamlessRotationCount = 0;
+            mService.startSeamlessRotation();
         }
 
         // We need to update our screen size information to match the new rotation. If the rotation
@@ -1053,40 +1051,27 @@
         // #computeScreenConfiguration() later.
         updateDisplayAndOrientation(getConfiguration().uiMode);
 
-        if (!inTransaction) {
-            if (SHOW_TRANSACTIONS) {
-                Slog.i(TAG_WM, ">>> OPEN TRANSACTION setRotationUnchecked");
-            }
-            mService.openSurfaceTransaction();
-        }
-        try {
-            // NOTE: We disable the rotation in the emulator because
-            //       it doesn't support hardware OpenGL emulation yet.
-            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
-                    && screenRotationAnimation.hasScreenshot()) {
-                if (screenRotationAnimation.setRotationInTransaction(rotation,
-                        MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
-                        mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
-                    mService.scheduleAnimationLocked();
-                }
-            }
-
-            if (rotateSeamlessly) {
-                forAllWindows(w -> {
-                    w.mWinAnimator.seamlesslyRotateWindow(oldRotation, rotation);
-                }, true /* traverseTopToBottom */);
-            }
-
-            mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
-        } finally {
-            if (!inTransaction) {
-                mService.closeSurfaceTransaction("setRotationUnchecked");
-                if (SHOW_LIGHT_TRANSACTIONS) {
-                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION setRotationUnchecked");
-                }
+        // NOTE: We disable the rotation in the emulator because
+        //       it doesn't support hardware OpenGL emulation yet.
+        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
+                && screenRotationAnimation.hasScreenshot()) {
+            if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
+                    MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
+                    mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
+                mService.scheduleAnimationLocked();
             }
         }
 
+        if (rotateSeamlessly) {
+            forAllWindows(w -> {
+                    w.mWinAnimator.seamlesslyRotateWindow(getPendingTransaction(),
+                            oldRotation, rotation);
+            }, true /* traverseTopToBottom */);
+        }
+
+        mService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
+        scheduleAnimation();
+
         forAllWindows(w -> {
             if (w.mHasSurface && !rotateSeamlessly) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
@@ -2808,7 +2793,7 @@
 
             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
+                if (mService.updateOrientationFromAppTokensLocked(mDisplayId)) {
                     setLayoutNeeded();
                     mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
                 }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 59bec74..0b0df6f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -141,6 +141,22 @@
         }
 
         @Override
+        public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars)
+                throws RemoteException {
+            long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mService.getWindowManagerLock()) {
+                    for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+                        mPendingAnimations.get(i).mTask.setCanAffectSystemUiFlags(behindSystemBars);
+                    }
+                    mService.mWindowPlacerLocked.requestTraversal();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public void setInputConsumerEnabled(boolean enabled) {
             if (DEBUG) Log.d(TAG, "setInputConsumerEnabled(" + enabled + "): mCanceled="
                     + mCanceled);
@@ -240,11 +256,16 @@
             return;
         }
         try {
-            final RemoteAnimationTarget[] appAnimations =
-                    new RemoteAnimationTarget[mPendingAnimations.size()];
+            final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>();
             for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
-                appAnimations[i] = mPendingAnimations.get(i).createRemoteAnimationApp();
+                final RemoteAnimationTarget target =
+                        mPendingAnimations.get(i).createRemoteAnimationApp();
+                if (target != null) {
+                    appAnimations.add(target);
+                }
             }
+            final RemoteAnimationTarget[] appTargets = appAnimations.toArray(
+                    new RemoteAnimationTarget[appAnimations.size()]);
             mPendingStart = false;
 
             final Rect minimizedHomeBounds =
@@ -253,7 +274,7 @@
             final Rect contentInsets =
                     mHomeAppToken != null && mHomeAppToken.findMainWindow() != null
                             ? mHomeAppToken.findMainWindow().mContentInsets : null;
-            mRunner.onAnimationStart_New(mController, appAnimations, contentInsets,
+            mRunner.onAnimationStart_New(mController, appTargets, contentInsets,
                     minimizedHomeBounds);
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to start recents animation", e);
@@ -284,6 +305,7 @@
                 + mPendingAnimations.size());
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
             final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
+            adapter.mTask.setCanAffectSystemUiFlags(true);
             adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
         }
         mPendingAnimations.clear();
@@ -367,6 +389,9 @@
             container.getRelativePosition(position);
             container.getBounds(bounds);
             final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
+            if (mainWindow == null) {
+                return null;
+            }
             mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
                     !mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
                     mainWindow.mContentInsets, mTask.getPrefixOrderIndex(), position, bounds,
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f32c275..32ae523 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -37,6 +37,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.SurfaceControl;
 import android.view.WindowManager;
 
 import com.android.internal.util.ArrayUtils;
@@ -128,6 +129,11 @@
     private final Handler mHandler;
 
     private String mCloseSystemDialogsReason;
+
+    // Only a seperate transaction until we seperate the apply surface changes
+    // transaction from the global transaction.
+    private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
+
     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
         if (w.mHasSurface) {
             try {
@@ -725,7 +731,7 @@
             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
             // TODO(multi-display): Update rotation for different displays separately.
             final int displayId = defaultDisplay.getDisplayId();
-            if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+            if (defaultDisplay.updateRotationUnchecked()) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
             } else {
                 mUpdateRotation = false;
@@ -735,7 +741,7 @@
             // PhoneWindowManager.
             final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
                     ? getDisplayContent(mService.mVr2dDisplayId) : null;
-            if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+            if (vrDisplay != null && vrDisplay.updateRotationUnchecked()) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
                         .sendToTarget();
             }
@@ -835,7 +841,8 @@
 
         // Give the display manager a chance to adjust properties like display rotation if it needs
         // to.
-        mService.mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
+        mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
+        SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 5a39de5..ad2fabb 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -224,8 +224,7 @@
     }
 
     public ScreenRotationAnimation(Context context, DisplayContent displayContent,
-            boolean inTransaction, boolean forceDefaultOrientation,
-            boolean isSecure, WindowManagerService service) {
+            boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
         mService = service;
         mContext = context;
         mDisplayContent = displayContent;
@@ -260,52 +259,39 @@
         mOriginalWidth = originalWidth;
         mOriginalHeight = originalHeight;
 
-        if (!inTransaction) {
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation");
-            mService.openSurfaceTransaction();
-        }
-
+        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
         try {
-            try {
-                mSurfaceControl = displayContent.makeOverlay()
-                        .setName("ScreenshotSurface")
-                        .setSize(mWidth, mHeight)
-                        .setSecure(isSecure)
-                        .build();
+            mSurfaceControl = displayContent.makeOverlay()
+                    .setName("ScreenshotSurface")
+                    .setSize(mWidth, mHeight)
+                    .setSecure(isSecure)
+                    .build();
 
-                // capture a screenshot into the surface we just created
-                Surface sur = new Surface();
-                sur.copyFrom(mSurfaceControl);
-                // TODO(multidisplay): we should use the proper display
-                SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
-                        SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
-                mSurfaceControl.setLayer(SCREEN_FREEZE_LAYER_SCREENSHOT);
-                mSurfaceControl.setAlpha(0);
-                mSurfaceControl.show();
-                sur.destroy();
-            } catch (OutOfResourcesException e) {
-                Slog.w(TAG, "Unable to allocate freeze surface", e);
-            }
-
-            if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
-                    "  FREEZE " + mSurfaceControl + ": CREATE");
-
-            setRotationInTransaction(originalRotation);
-        } finally {
-            if (!inTransaction) {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation");
-            }
+            // capture a screenshot into the surface we just created
+            Surface sur = new Surface();
+            sur.copyFrom(mSurfaceControl);
+            // TODO(multidisplay): we should use the proper display
+            SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
+                            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
+            t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
+            t.setAlpha(mSurfaceControl, 0);
+            t.show(mSurfaceControl);
+            sur.destroy();
+        } catch (OutOfResourcesException e) {
+            Slog.w(TAG, "Unable to allocate freeze surface", e);
         }
+
+        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
+                "  FREEZE " + mSurfaceControl + ": CREATE");
+        setRotation(t, originalRotation);
+        t.apply();
     }
 
     boolean hasScreenshot() {
         return mSurfaceControl != null;
     }
 
-    private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
+    private void setSnapshotTransform(SurfaceControl.Transaction t, Matrix matrix, float alpha) {
         if (mSurfaceControl != null) {
             matrix.getValues(mTmpFloats);
             float x = mTmpFloats[Matrix.MTRANS_X];
@@ -315,11 +301,11 @@
                 x -= mCurrentDisplayRect.left;
                 y -= mCurrentDisplayRect.top;
             }
-            mSurfaceControl.setPosition(x, y);
-            mSurfaceControl.setMatrix(
+            t.setPosition(mSurfaceControl, x, y);
+            t.setMatrix(mSurfaceControl,
                     mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
                     mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
-            mSurfaceControl.setAlpha(alpha);
+            t.setAlpha(mSurfaceControl, alpha);
             if (DEBUG_TRANSFORMS) {
                 float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
                 float[] dstPnts = new float[4];
@@ -353,8 +339,7 @@
         }
     }
 
-    // Must be called while in a transaction.
-    private void setRotationInTransaction(int rotation) {
+    private void setRotation(SurfaceControl.Transaction t, int rotation) {
         mCurRotation = rotation;
 
         // Compute the transformation matrix that must be applied
@@ -364,15 +349,14 @@
         createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
 
         if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
-        setSnapshotTransformInTransaction(mSnapshotInitialMatrix, 1.0f);
+        setSnapshotTransform(t, mSnapshotInitialMatrix, 1.0f);
     }
 
-    // Must be called while in a transaction.
-    public boolean setRotationInTransaction(int rotation,
+    public boolean setRotation(SurfaceControl.Transaction t, int rotation,
             long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) {
-        setRotationInTransaction(rotation);
+        setRotation(t, rotation);
         if (TWO_PHASE_ANIMATION) {
-            return startAnimation(maxAnimationDuration, animationScale,
+            return startAnimation(t, maxAnimationDuration, animationScale,
                     finalWidth, finalHeight, false, 0, 0);
         }
 
@@ -383,7 +367,7 @@
     /**
      * Returns true if animating.
      */
-    private boolean startAnimation(long maxAnimationDuration,
+    private boolean startAnimation(SurfaceControl.Transaction t, long maxAnimationDuration,
             float animationScale, int finalWidth, int finalHeight, boolean dismissing,
             int exitAnim, int enterAnim) {
         if (mSurfaceControl == null) {
@@ -542,11 +526,6 @@
 
         final int layerStack = mDisplayContent.getDisplay().getLayerStack();
         if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
-
             // Compute the transformation matrix that must be applied
             // the the black frame to make it stay in the initial position
             // before the new screen rotation.  This is different than the
@@ -559,24 +538,15 @@
                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                         mOriginalWidth*2, mOriginalHeight*2);
                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
-                mCustomBlackFrame = new BlackFrame(outer, inner,
+                mCustomBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_CUSTOM, mDisplayContent, false);
-                mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
+                mCustomBlackFrame.setMatrix(t, mFrameInitialMatrix);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
         if (!customAnim && mExitingBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
             try {
                 // Compute the transformation matrix that must be applied
                 // the the black frame to make it stay in the initial position
@@ -599,38 +569,23 @@
                             mOriginalWidth*2, mOriginalHeight*2);
                     inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
                 }
-                mExitingBlackFrame = new BlackFrame(outer, inner,
+                mExitingBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation);
-                mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
+                mExitingBlackFrame.setMatrix(t, mFrameInitialMatrix);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
         if (customAnim && mEnteringBlackFrame == null) {
-            if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                    TAG_WM,
-                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            mService.openSurfaceTransaction();
-
             try {
                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
                         finalWidth*2, finalHeight*2);
                 Rect inner = new Rect(0, 0, finalWidth, finalHeight);
-                mEnteringBlackFrame = new BlackFrame(outer, inner,
+                mEnteringBlackFrame = new BlackFrame(t, outer, inner,
                         SCREEN_FREEZE_LAYER_ENTER, mDisplayContent, false);
             } catch (OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
-            } finally {
-                mService.closeSurfaceTransaction("ScreenRotationAnimation.startAnimation");
-                if (SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
-                        TAG_WM,
-                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
             }
         }
 
@@ -640,7 +595,7 @@
     /**
      * Returns true if animating.
      */
-    public boolean dismiss(long maxAnimationDuration,
+    public boolean dismiss(SurfaceControl.Transaction t, long maxAnimationDuration,
             float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
         if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
         if (mSurfaceControl == null) {
@@ -648,7 +603,7 @@
             return false;
         }
         if (!mStarted) {
-            startAnimation(maxAnimationDuration, animationScale, finalWidth, finalHeight,
+            startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight,
                     true, exitAnim, enterAnim);
         }
         if (!mStarted) {
@@ -919,7 +874,7 @@
         return more;
     }
 
-    void updateSurfacesInTransaction() {
+    void updateSurfaces(SurfaceControl.Transaction t) {
         if (!mStarted) {
             return;
         }
@@ -927,28 +882,28 @@
         if (mSurfaceControl != null) {
             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
                 if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
-                mSurfaceControl.hide();
+                t.hide(mSurfaceControl);
             }
         }
 
         if (mCustomBlackFrame != null) {
             if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
-                mCustomBlackFrame.hide();
+                mCustomBlackFrame.hide(t);
             } else {
-                mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
+                mCustomBlackFrame.setMatrix(t, mFrameTransformation.getMatrix());
             }
         }
 
         if (mExitingBlackFrame != null) {
             if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
-                mExitingBlackFrame.hide();
+                mExitingBlackFrame.hide(t);
             } else {
                 mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
-                mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
+                mExitingBlackFrame.setMatrix(t, mExitFrameFinalMatrix);
                 if (mForceDefaultOrientation) {
-                    mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
+                    mExitingBlackFrame.setAlpha(t, mExitTransformation.getAlpha());
                 }
             }
         }
@@ -956,13 +911,13 @@
         if (mEnteringBlackFrame != null) {
             if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
-                mEnteringBlackFrame.hide();
+                mEnteringBlackFrame.hide(t);
             } else {
-                mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
+                mEnteringBlackFrame.setMatrix(t, mEnterTransformation.getMatrix());
             }
         }
 
-        setSnapshotTransformInTransaction(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+        setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha());
     }
 
     public boolean stepAnimationLocked(long now) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 2e86351..a403e6f2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -96,6 +96,9 @@
     private Dimmer mDimmer = new Dimmer(this);
     private final Rect mTmpDimBoundsRect = new Rect();
 
+    /** @see #setCanAffectSystemUiFlags */
+    private boolean mCanAffectSystemUiFlags = true;
+
     Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
             boolean supportsPictureInPicture, TaskDescription taskDescription,
             TaskWindowContainerController controller) {
@@ -627,6 +630,21 @@
         callback.accept(this);
     }
 
+    /**
+     * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
+     *                               flags. See {@link WindowState#canAffectSystemUiFlags()}.
+     */
+    void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
+        mCanAffectSystemUiFlags = canAffectSystemUiFlags;
+    }
+
+    /**
+     * @see #setCanAffectSystemUiFlags
+     */
+    boolean canAffectSystemUiFlags() {
+        return mCanAffectSystemUiFlags;
+    }
+
     @Override
     public String toString() {
         return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}";
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index ab10197..793ffce 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -30,6 +30,7 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.view.Choreographer;
+import android.view.SurfaceControl;
 
 import com.android.server.AnimationThread;
 import com.android.server.policy.WindowManagerPolicy;
@@ -94,6 +95,8 @@
     private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
     private boolean mInExecuteAfterPrepareSurfacesRunnables;
 
+    private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+
     WindowAnimator(final WindowManagerService service) {
         mService = service;
         mContext = service.mContext;
@@ -203,7 +206,7 @@
                     final ScreenRotationAnimation screenRotationAnimation =
                             mDisplayContentsAnimators.valueAt(i).mScreenRotationAnimation;
                     if (screenRotationAnimation != null) {
-                        screenRotationAnimation.updateSurfacesInTransaction();
+                        screenRotationAnimation.updateSurfaces(mTransaction);
                     }
                     orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
                     //TODO (multidisplay): Magnification is supported only for the default display.
@@ -219,6 +222,8 @@
                 if (mService.mWatermark != null) {
                     mService.mWatermark.drawIfNeeded();
                 }
+
+                SurfaceControl.mergeToGlobalTransaction(mTransaction);
             } catch (RuntimeException e) {
                 Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
             } finally {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 563d792..be009d2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -667,11 +667,18 @@
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
 
-    // A count of the windows which are 'seamlessly rotated', e.g. a surface
-    // at an old orientation is being transformed. We freeze orientation updates
-    // while any windows are seamlessly rotated, so we need to track when this
-    // hits zero so we can apply deferred orientation updates.
-    int mSeamlessRotationCount = 0;
+    /**
+     * A count of the windows which are 'seamlessly rotated', e.g. a surface
+     * at an old orientation is being transformed. We freeze orientation updates
+     * while any windows are seamlessly rotated, so we need to track when this
+     * hits zero so we can apply deferred orientation updates.
+     */
+    private int mSeamlessRotationCount = 0;
+    /**
+     * True in the interval from starting seamless rotation until the last rotated
+     * window draws in the new orientation.
+     */
+    private boolean mRotatingSeamlessly = false;
 
     private final class SettingsObserver extends ContentObserver {
         private final Uri mDisplayInversionEnabledUri =
@@ -809,6 +816,8 @@
     SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
     TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
 
+    private final SurfaceControl.Transaction mTransaction = mTransactionFactory.make();
+
     static void boostPriorityForLockedSection() {
         sThreadPriorityBooster.boost();
     }
@@ -1487,7 +1496,7 @@
             if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
                     + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
 
-            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false, displayId)) {
+            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(displayId)) {
                 reportNewConfig = true;
             }
         }
@@ -2049,7 +2058,7 @@
 
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                     "relayoutWindow: updateOrientationFromAppTokens");
-            configChanged = updateOrientationFromAppTokensLocked(false, displayId);
+            configChanged = updateOrientationFromAppTokensLocked(displayId);
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
 
             if (toBeDisplayed && win.mIsWallpaper) {
@@ -2340,7 +2349,7 @@
         }
         Configuration config = null;
 
-        if (updateOrientationFromAppTokensLocked(false, displayId)) {
+        if (updateOrientationFromAppTokensLocked(displayId)) {
             // If we changed the orientation but mOrientationChangeComplete is already true,
             // we used seamless rotation, and we don't need to freeze the screen.
             if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
@@ -2367,7 +2376,7 @@
                 int anim[] = new int[2];
                 mPolicy.selectRotationAnimationLw(anim);
 
-                startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
+                startFreezingDisplayLocked(anim[0], anim[1], displayContent);
                 config = new Configuration(mTempConfiguration);
             }
         }
@@ -2387,7 +2396,7 @@
      * tokens.
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
      */
-    boolean updateOrientationFromAppTokensLocked(boolean inTransaction, int displayId) {
+    boolean updateOrientationFromAppTokensLocked(int displayId) {
         long ident = Binder.clearCallingIdentity();
         try {
             final DisplayContent dc = mRoot.getDisplayContent(displayId);
@@ -2400,7 +2409,7 @@
                 if (dc.isDefaultDisplay) {
                     mPolicy.setCurrentOrientationLw(req);
                 }
-                if (dc.updateRotationUnchecked(inTransaction)) {
+                if (dc.updateRotationUnchecked()) {
                     // changed
                     return true;
                 }
@@ -2873,7 +2882,7 @@
                 mClientFreezingScreen = true;
                 final long origId = Binder.clearCallingIdentity();
                 try {
-                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
+                    startFreezingDisplayLocked(exitAnim, enterAnim);
                     mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
                     mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
                 } finally {
@@ -3774,8 +3783,7 @@
             if (mDeferredRotationPauseCount == 0) {
                 // TODO(multi-display): Update rotation for different displays separately.
                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                final boolean changed = displayContent.updateRotationUnchecked(
-                        false /* inTransaction */);
+                final boolean changed = displayContent.updateRotationUnchecked();
                 if (changed) {
                     mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
                             .sendToTarget();
@@ -3800,8 +3808,7 @@
             synchronized (mWindowMap) {
                 final DisplayContent displayContent = getDefaultDisplayContentLocked();
                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
-                rotationChanged = displayContent.updateRotationUnchecked(
-                        false /* inTransaction */);
+                rotationChanged = displayContent.updateRotationUnchecked();
                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 if (!rotationChanged || forceRelayout) {
                     displayContent.setLayoutNeeded();
@@ -5326,8 +5333,7 @@
         displayContent.setLayoutNeeded();
 
         final int displayId = displayContent.getDisplayId();
-        boolean configChanged = updateOrientationFromAppTokensLocked(false /* inTransaction */,
-                displayId);
+        boolean configChanged = updateOrientationFromAppTokensLocked(displayId);
         final Configuration currentDisplayConfig = displayContent.getConfiguration();
         mTempConfiguration.setTo(currentDisplayConfig);
         displayContent.computeScreenConfiguration(mTempConfiguration);
@@ -5335,7 +5341,7 @@
 
         if (configChanged) {
             mWaitingForConfig = true;
-            startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
+            startFreezingDisplayLocked(0 /* exitAnim */,
                     0 /* enterAnim */, displayContent);
             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
         }
@@ -5651,14 +5657,14 @@
         return false;
     }
 
-    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
-        startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
+    void startFreezingDisplayLocked(int exitAnim, int enterAnim) {
+        startFreezingDisplayLocked(exitAnim, enterAnim,
                 getDefaultDisplayContentLocked());
     }
 
-    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
+    void startFreezingDisplayLocked(int exitAnim, int enterAnim,
             DisplayContent displayContent) {
-        if (mDisplayFrozen) {
+        if (mDisplayFrozen || mRotatingSeamlessly) {
             return;
         }
 
@@ -5669,8 +5675,8 @@
         }
 
         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
-                "startFreezingDisplayLocked: inTransaction=" + inTransaction
-                + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim
+                "startFreezingDisplayLocked: exitAnim="
+                + exitAnim + " enterAnim=" + enterAnim
                 + " called by " + Debug.getCallers(8));
         mScreenFrozenLock.acquire();
 
@@ -5714,7 +5720,7 @@
 
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
+                    mPolicy.isDefaultOrientationForced(), isSecure,
                     this);
             mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
                     screenRotationAnimation);
@@ -5777,9 +5783,10 @@
             if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, false)) {
                 mExitAnimId = mEnterAnimId = 0;
             }
-            if (screenRotationAnimation.dismiss(MAX_ANIMATION_DURATION,
+            if (screenRotationAnimation.dismiss(mTransaction, MAX_ANIMATION_DURATION,
                     getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
                         displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
+                mTransaction.apply();
                 scheduleAnimationLocked();
             } else {
                 screenRotationAnimation.kill();
@@ -5802,7 +5809,7 @@
         // to avoid inconsistent states.  However, something interesting
         // could have actually changed during that time so re-evaluate it
         // now to catch that.
-        configChanged = updateOrientationFromAppTokensLocked(false, displayId);
+        configChanged = updateOrientationFromAppTokensLocked(displayId);
 
         // A little kludge: a lot could have happened while the
         // display was frozen, so now that we are coming back we
@@ -5816,8 +5823,7 @@
 
         if (updateRotation) {
             if (DEBUG_ORIENTATION) Slog.d(TAG_WM, "Performing post-rotate rotation");
-            configChanged |= displayContent.updateRotationUnchecked(
-                    false /* inTransaction */);
+            configChanged |= displayContent.updateRotationUnchecked();
         }
 
         if (configChanged) {
@@ -7027,8 +7033,10 @@
             if (DEBUG_ORIENTATION) {
                 Slog.i(TAG, "Performing post-rotate rotation after seamless rotation");
             }
+            finishSeamlessRotation();
+
             final DisplayContent displayContent = w.getDisplayContent();
-            if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
+            if (displayContent.updateRotationUnchecked()) {
                 mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayContent.getDisplayId())
                         .sendToTarget();
             }
@@ -7438,5 +7446,31 @@
         mH.obtainMessage(H.SET_RUNNING_REMOTE_ANIMATION, pid, runningRemoteAnimation ? 1 : 0)
                 .sendToTarget();
     }
-}
 
+    void startSeamlessRotation() {
+        // We are careful to reset this in case a window was removed before it finished
+        // seamless rotation.
+        mSeamlessRotationCount = 0;
+
+        mRotatingSeamlessly = true;
+    }
+
+    void finishSeamlessRotation() {
+        mRotatingSeamlessly = false;
+    }
+
+    /**
+     * Called when the state of lock task mode changes. This should be used to disable immersive
+     * mode confirmation.
+     *
+     * @param lockTaskState the new lock task mode state. One of
+     *                      {@link ActivityManager#LOCK_TASK_MODE_NONE},
+     *                      {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+     *                      {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
+     */
+    public void onLockTaskStateChanged(int lockTaskState) {
+        synchronized (mWindowMap) {
+            mPolicy.onLockTaskStateChangedLw(lockTaskState);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 297e067..8866fe5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1573,7 +1573,9 @@
             final boolean exiting = mAnimatingExit || mDestroying;
             return shown && !exiting;
         } else {
-            return !mAppToken.isHidden();
+            final Task task = getTask();
+            final boolean canFromTask = task != null && task.canAffectSystemUiFlags();
+            return canFromTask && !mAppToken.isHidden();
         }
     }
 
@@ -2013,7 +2015,7 @@
             removeImmediately();
             // Removing a visible window will effect the computed orientation
             // So just update orientation if needed.
-            if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) {
+            if (wasVisible && mService.updateOrientationFromAppTokensLocked(displayId)) {
                 mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
             }
             mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 13f05e0..46a9961 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1415,7 +1415,8 @@
         }
     }
 
-    void seamlesslyRotateWindow(int oldRotation, int newRotation) {
+    void seamlesslyRotateWindow(SurfaceControl.Transaction t,
+            int oldRotation, int newRotation) {
         final WindowState w = mWin;
         if (!w.isVisibleNow() || w.mIsWallpaper) {
             return;
@@ -1456,11 +1457,9 @@
         float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y];
         float nx = mService.mTmpFloats[Matrix.MTRANS_X];
         float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
-        mSurfaceController.setPositionInTransaction(nx, ny, false);
-        mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale,
-                DtDx * w.mVScale,
-                DtDy * w.mHScale,
-                DsDy * w.mVScale, false);
+        mSurfaceController.setPosition(t, nx, ny, false);
+        mSurfaceController.setMatrix(t, DsDx * w.mHScale, DtDx * w.mVScale, DtDy
+                * w.mHScale, DsDy * w.mVScale, false);
     }
 
     /** The force-scaled state for a given window can persist past
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 9d6f8f7..f6c0a54 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -242,6 +242,11 @@
     }
 
     void setPositionInTransaction(float left, float top, boolean recoveringMemory) {
+        setPosition(null, left, top, recoveringMemory);
+    }
+
+    void setPosition(SurfaceControl.Transaction t, float left, float top,
+            boolean recoveringMemory) {
         final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
         if (surfaceMoved) {
             mSurfaceX = left;
@@ -251,7 +256,11 @@
                 if (SHOW_TRANSACTIONS) logSurface(
                         "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
 
-                mSurfaceControl.setPosition(left, top);
+                if (t == null) {
+                    mSurfaceControl.setPosition(left, top);
+                } else {
+                    t.setPosition(mSurfaceControl, left, top);
+                }
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error positioning surface of " + this
                         + " pos=(" + left + "," + top + ")", e);
@@ -268,6 +277,11 @@
 
     void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy,
             boolean recoveringMemory) {
+        setMatrix(null, dsdx, dtdx, dtdy, dsdy, false);
+    }
+
+    void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx,
+            float dtdy, float dsdy, boolean recoveringMemory) {
         final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx ||
                                       mLastDtdy != dtdy || mLastDsdy != dsdy;
         if (!matrixChanged) {
@@ -282,8 +296,11 @@
         try {
             if (SHOW_TRANSACTIONS) logSurface(
                     "MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
-            mSurfaceControl.setMatrix(
-                    dsdx, dtdx, dtdy, dsdy);
+            if (t == null) {
+                mSurfaceControl.setMatrix(dsdx, dtdx, dtdy, dsdy);
+            } else {
+                t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
+            }
         } catch (RuntimeException e) {
             // If something goes wrong with the surface (such
             // as running out of memory), don't take down the
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4179590..fc5e33a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -52,6 +52,7 @@
 import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 
+import android.app.WindowConfiguration;
 import android.os.Debug;
 import android.os.Trace;
 import android.util.ArraySet;
@@ -294,12 +295,14 @@
         // what will control the animation theme. If all closing windows are obscured, then there is
         // no need to do an animation. This is the case, for example, when this transition is being
         // done behind a dream window.
+        final ArraySet<Integer> activityTypes = collectActivityTypes(mService.mOpeningApps,
+                mService.mClosingApps);
         final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw()
-                ? findAnimLayoutParamsToken(transit)
+                ? findAnimLayoutParamsToken(transit, activityTypes)
                 : null;
 
         final LayoutParams animLp = getAnimLp(animLpToken);
-        overrideWithRemoteAnimationIfSet(animLpToken, transit);
+        overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes);
 
         final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps)
                 || containsVoiceInteraction(mService.mOpeningApps);
@@ -361,13 +364,14 @@
      * Overrides the pending transition with the remote animation defined for the transition in the
      * set of defined remote animations in the app window token.
      */
-    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit) {
+    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit,
+            ArraySet<Integer> activityTypes) {
         if (animLpToken == null) {
             return;
         }
         final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
         if (definition != null) {
-            final RemoteAnimationAdapter adapter = definition.getAdapter(transit);
+            final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
             if (adapter != null) {
                 mService.mAppTransition.overridePendingAppTransitionRemote(adapter);
             }
@@ -377,13 +381,14 @@
     /**
      * @return The window token that determines the animation theme.
      */
-    private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit) {
+    private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit,
+            ArraySet<Integer> activityTypes) {
         AppWindowToken result;
 
         // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
         result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
                 w -> w.getRemoteAnimationDefinition() != null
-                        && w.getRemoteAnimationDefinition().hasTransition(transit));
+                        && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
         if (result != null) {
             return result;
         }
@@ -396,6 +401,22 @@
                 w -> w.findMainWindow() != null);
     }
 
+    /**
+     * @return The set of {@link WindowConfiguration.ActivityType}s contained in the set of apps in
+     *         {@code array1} and {@code array2}.
+     */
+    private ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1,
+            ArraySet<AppWindowToken> array2) {
+        final ArraySet<Integer> result = new ArraySet<>();
+        for (int i = array1.size() - 1; i >= 0; i--) {
+            result.add(array1.valueAt(i).getActivityType());
+        }
+        for (int i = array2.size() - 1; i >= 0; i--) {
+            result.add(array2.valueAt(i).getActivityType());
+        }
+        return result;
+    }
+
     private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
             ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) {
         final int array1count = array1.size();
@@ -403,12 +424,9 @@
         int bestPrefixOrderIndex = Integer.MIN_VALUE;
         AppWindowToken bestToken = null;
         for (int i = 0; i < count; i++) {
-            final AppWindowToken wtoken;
-            if (i < array1count) {
-                wtoken = array1.valueAt(i);
-            } else {
-                wtoken = array2.valueAt(i - array1count);
-            }
+            final AppWindowToken wtoken = i < array1count
+                    ? array1.valueAt(i)
+                    : array2.valueAt(i - array1count);
             final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
             if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
                 bestPrefixOrderIndex = prefixOrderIndex;
@@ -559,7 +577,8 @@
                         + wtoken.allDrawn + " startingDisplayed="
                         + wtoken.startingDisplayed + " startingMoved="
                         + wtoken.startingMoved + " isRelaunching()="
-                        + wtoken.isRelaunching());
+                        + wtoken.isRelaunching() + " startingWindow="
+                        + wtoken.startingWindow);
 
 
                 final boolean allDrawn = wtoken.allDrawn && !wtoken.isRelaunching();
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index aed57e3..3d7fdbdd 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -62,7 +62,8 @@
     $(call all-java-files-under, ../../core/java/android/app/backup) \
     $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
     ../../core/java/android/content/pm/PackageInfo.java \
-    ../../core/java/android/app/IBackupAgent.aidl
+    ../../core/java/android/app/IBackupAgent.aidl \
+    ../../core/java/android/util/KeyValueSettingObserver.java
 
 LOCAL_AIDL_INCLUDES := \
     $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index 0752537..2a32c2e 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -18,79 +18,218 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.app.AlarmManager;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-
+import android.util.KeyValueSettingObserver;
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderClasses;
 import com.android.server.testing.SystemLoaderPackages;
-
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(manifest = Config.NONE, sdk = 26)
 @SystemLoaderPackages({"com.android.server.backup"})
+@SystemLoaderClasses({KeyValueSettingObserver.class})
 @Presubmit
 public class BackupManagerConstantsTest {
     private static final String PACKAGE_NAME = "some.package.name";
     private static final String ANOTHER_PACKAGE_NAME = "another.package.name";
 
+    private ContentResolver mContentResolver;
+    private BackupManagerConstants mConstants;
+
     @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
+    public void setUp() {
+        final Context context = RuntimeEnvironment.application.getApplicationContext();
+
+        mContentResolver = context.getContentResolver();
+        mConstants = new BackupManagerConstants(new Handler(), mContentResolver);
+        mConstants.start();
+    }
+
+    @After
+    public void tearDown() {
+        mConstants.stop();
     }
 
     @Test
-    public void testDefaultValues() throws Exception {
-        final Context context = RuntimeEnvironment.application.getApplicationContext();
-        final Handler handler = new Handler();
+    public void testGetConstants_afterConstructorWithStart_returnsDefaultValues() {
+        long keyValueBackupIntervalMilliseconds =
+                mConstants.getKeyValueBackupIntervalMilliseconds();
+        long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+        boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging();
+        int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+        long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+        boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging();
+        int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType();
+        String[] backupFinishedNotificationReceivers =
+                mConstants.getBackupFinishedNotificationReceivers();
 
-        Settings.Secure.putString(
-                context.getContentResolver(), Settings.Secure.BACKUP_MANAGER_CONSTANTS, null);
+        assertThat(keyValueBackupIntervalMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+        assertThat(keyValueBackupFuzzMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+        assertThat(keyValueBackupRequireCharging)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+        assertThat(keyValueBackupRequiredNetworkType)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+        assertThat(fullBackupIntervalMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+        assertThat(fullBackupRequireCharging)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+        assertThat(fullBackupRequiredNetworkType)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+        assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]);
+    }
 
-        final BackupManagerConstants constants =
-                new BackupManagerConstants(handler, context.getContentResolver());
+    /**
+     * Tests that if there is a setting change when we are not currently observing the setting, that
+     * once we start observing again, we receive the most up-to-date value.
+     */
+    @Test
+    public void testGetConstant_withSettingChangeBeforeStart_updatesValues() {
+        mConstants.stop();
+        long testInterval =
+                BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2;
+        final String setting =
+                BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS + "=" + testInterval;
+        putStringAndNotify(setting);
 
-        assertThat(constants.getKeyValueBackupIntervalMilliseconds())
-                .isEqualTo(4 * AlarmManager.INTERVAL_HOUR);
-        assertThat(constants.getKeyValueBackupFuzzMilliseconds()).isEqualTo(10 * 60 * 1000);
-        assertThat(constants.getKeyValueBackupRequireCharging()).isEqualTo(true);
-        assertThat(constants.getKeyValueBackupRequiredNetworkType()).isEqualTo(1);
+        mConstants.start();
 
-        assertThat(constants.getFullBackupIntervalMilliseconds())
-                .isEqualTo(24 * AlarmManager.INTERVAL_HOUR);
-        assertThat(constants.getFullBackupRequireCharging()).isEqualTo(true);
-        assertThat(constants.getFullBackupRequiredNetworkType()).isEqualTo(2);
-        assertThat(constants.getBackupFinishedNotificationReceivers()).isEqualTo(new String[0]);
+        long keyValueBackupIntervalMilliseconds =
+                mConstants.getKeyValueBackupIntervalMilliseconds();
+        assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testInterval);
     }
 
     @Test
-    public void testParseNotificationReceivers() throws Exception {
-        final Context context = RuntimeEnvironment.application.getApplicationContext();
-        final Handler handler = new Handler();
+    public void testGetConstants_whenSettingIsNull_returnsDefaultValues() {
+        putStringAndNotify(null);
 
-        final String recieversSetting =
-                "backup_finished_notification_receivers="
+        long keyValueBackupIntervalMilliseconds =
+                mConstants.getKeyValueBackupIntervalMilliseconds();
+        long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+        boolean keyValueBackupRequireCharging = mConstants.getKeyValueBackupRequireCharging();
+        int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+        long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+        boolean fullBackupRequireCharging = mConstants.getFullBackupRequireCharging();
+        int fullBackupRequiredNetworkType = mConstants.getFullBackupRequiredNetworkType();
+        String[] backupFinishedNotificationReceivers =
+                mConstants.getBackupFinishedNotificationReceivers();
+
+        assertThat(keyValueBackupIntervalMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS);
+        assertThat(keyValueBackupFuzzMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+        assertThat(keyValueBackupRequireCharging)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRE_CHARGING);
+        assertThat(keyValueBackupRequiredNetworkType)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+        assertThat(fullBackupIntervalMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS);
+        assertThat(fullBackupRequireCharging)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRE_CHARGING);
+        assertThat(fullBackupRequiredNetworkType)
+                .isEqualTo(BackupManagerConstants.DEFAULT_FULL_BACKUP_REQUIRED_NETWORK_TYPE);
+        assertThat(backupFinishedNotificationReceivers).isEqualTo(new String[0]);
+    }
+
+    /**
+     * Test passing in a malformed setting string. The setting expects
+     * "key1=value,key2=value,key3=value..." but we pass in "key1=,value"
+     */
+    @Test
+    public void testGetConstant_whenSettingIsMalformed_doesNotUpdateParamsOrThrow() {
+        long testFuzz = BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS * 2;
+        final String invalidSettingFormat =
+                BackupManagerConstants.KEY_VALUE_BACKUP_FUZZ_MILLISECONDS + "=," + testFuzz;
+        putStringAndNotify(invalidSettingFormat);
+
+        long keyValueBackupFuzzMilliseconds = mConstants.getKeyValueBackupFuzzMilliseconds();
+
+        assertThat(keyValueBackupFuzzMilliseconds)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_FUZZ_MILLISECONDS);
+    }
+
+    /**
+     * Test passing in an invalid value type. {@link
+     * BackupManagerConstants#KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE} expects an integer, but we
+     * pass in a boolean.
+     */
+    @Test
+    public void testGetConstant_whenSettingHasInvalidType_doesNotUpdateParamsOrThrow() {
+        boolean testValue = true;
+        final String invalidSettingType =
+                BackupManagerConstants.KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE + "=" + testValue;
+        putStringAndNotify(invalidSettingType);
+
+        int keyValueBackupRequiredNetworkType = mConstants.getKeyValueBackupRequiredNetworkType();
+
+        assertThat(keyValueBackupRequiredNetworkType)
+                .isEqualTo(BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_REQUIRED_NETWORK_TYPE);
+    }
+
+    @Test
+    public void testGetConstants_afterSettingChange_updatesValues() {
+        long testKVInterval =
+                BackupManagerConstants.DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS * 2;
+        long testFullInterval =
+                BackupManagerConstants.DEFAULT_FULL_BACKUP_INTERVAL_MILLISECONDS * 2;
+        final String intervalSetting =
+                BackupManagerConstants.KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS
+                        + "="
+                        + testKVInterval
+                        + ","
+                        + BackupManagerConstants.FULL_BACKUP_INTERVAL_MILLISECONDS
+                        + "="
+                        + testFullInterval;
+        putStringAndNotify(intervalSetting);
+
+        long keyValueBackupIntervalMilliseconds =
+                mConstants.getKeyValueBackupIntervalMilliseconds();
+        long fullBackupIntervalMilliseconds = mConstants.getFullBackupIntervalMilliseconds();
+
+        assertThat(keyValueBackupIntervalMilliseconds).isEqualTo(testKVInterval);
+        assertThat(fullBackupIntervalMilliseconds).isEqualTo(testFullInterval);
+    }
+
+    @Test
+    public void testBackupNotificationReceivers_afterSetting_updatesAndParsesCorrectly() {
+        final String receiversSetting =
+                BackupManagerConstants.BACKUP_FINISHED_NOTIFICATION_RECEIVERS
+                        + "="
                         + PACKAGE_NAME
                         + ':'
                         + ANOTHER_PACKAGE_NAME;
-        Settings.Secure.putString(
-                context.getContentResolver(),
-                Settings.Secure.BACKUP_MANAGER_CONSTANTS,
-                recieversSetting);
+        putStringAndNotify(receiversSetting);
 
-        final BackupManagerConstants constants =
-                new BackupManagerConstants(handler, context.getContentResolver());
-
-        assertThat(constants.getBackupFinishedNotificationReceivers())
+        String[] backupFinishedNotificationReceivers =
+                mConstants.getBackupFinishedNotificationReceivers();
+        assertThat(backupFinishedNotificationReceivers)
                 .isEqualTo(new String[] {PACKAGE_NAME, ANOTHER_PACKAGE_NAME});
     }
+
+    /**
+     * Robolectric does not notify observers of changes to settings so we have to trigger it here.
+     * Currently, the mock of {@link Settings.Secure#putString(ContentResolver, String, String)}
+     * only stores the value. TODO: Implement properly in ShadowSettings.
+     */
+    private void putStringAndNotify(String value) {
+        Settings.Secure.putString(
+                mContentResolver, Settings.Secure.BACKUP_MANAGER_CONSTANTS, value);
+
+        // We pass null as the observer since notifyChange iterates over all available observers and
+        // we don't have access to the local observer.
+        mContentResolver.notifyChange(
+                Settings.Secure.getUriFor(Settings.Secure.BACKUP_MANAGER_CONSTANTS),
+                /*observer*/ null);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index ac212dd..03e870a 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -222,35 +222,4 @@
         verify(mService.mStackSupervisor, times(1)).canPlaceEntityOnDisplay(anyInt(), eq(expected),
                 anyInt(), anyInt(), eq(record.info));
     }
-
-    @Test
-    public void testFinishingAfterDestroying() throws Exception {
-        assertFalse(mActivity.finishing);
-        mActivity.setState(DESTROYING, "testFinishingAfterDestroying");
-        assertTrue(mActivity.isState(DESTROYING));
-        assertTrue(mActivity.finishing);
-    }
-
-    @Test
-    public void testFinishingAfterDestroyed() throws Exception {
-        assertFalse(mActivity.finishing);
-        mActivity.setState(DESTROYED, "testFinishingAfterDestroyed");
-        assertTrue(mActivity.isState(DESTROYED));
-        assertTrue(mActivity.finishing);
-    }
-
-    @Test
-    public void testSetInvalidState() throws Exception {
-        mActivity.setState(DESTROYED, "testInvalidState");
-
-        boolean exceptionEncountered = false;
-
-        try {
-            mActivity.setState(FINISHING, "testInvalidState");
-        } catch (IllegalArgumentException e) {
-            exceptionEncountered = true;
-        }
-
-        assertTrue(exceptionEncountered);
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index bda68d1..f17bfa4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -479,28 +479,6 @@
     }
 
     @Test
-    public void testSuppressMultipleDestroy() throws Exception {
-        final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
-        final ClientLifecycleManager lifecycleManager = mock(ClientLifecycleManager.class);
-        final ProcessRecord app = r.app;
-
-        // The mocked lifecycle manager must be set on the ActivityStackSupervisor's reference to
-        // the service rather than mService as mService is a spy and setting the value will not
-        // propagate as ActivityManagerService hands its own reference to the
-        // ActivityStackSupervisor during construction.
-        ((TestActivityManagerService) mSupervisor.mService).setLifecycleManager(lifecycleManager);
-
-        mStack.destroyActivityLocked(r, true, "first invocation");
-        verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
-                eq(r.appToken), any(DestroyActivityItem.class));
-        assertTrue(r.isState(DESTROYED, DESTROYING));
-
-        mStack.destroyActivityLocked(r, true, "second invocation");
-        verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
-                eq(r.appToken), any(DestroyActivityItem.class));
-    }
-
-    @Test
     public void testFinishDisabledPackageActivities() throws Exception {
         final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
         final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 24566fc..376f5b1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -24,6 +25,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static org.junit.Assert.assertFalse;
@@ -74,7 +76,7 @@
 import java.util.Set;
 
 /**
- * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+ * atest FrameworksServicesTests:RecentTasksTest
  */
 @MediumTest
 @Presubmit
@@ -145,7 +147,7 @@
         mRecentTasks = (TestRecentTasks) mService.getRecentTasks();
         mRecentTasks.loadParametersFromResources(mContext.getResources());
         mHomeStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
         mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         ((MyTestActivityStackSupervisor) mService.mStackSupervisor).setHomeStack(mHomeStack);
@@ -236,7 +238,7 @@
     }
 
     @Test
-    public void testAddTasksMultipleTasks_expectNoTrim() throws Exception {
+    public void testAddTasksMultipleDocumentTasks_expectNoTrim() throws Exception {
         // Add same multiple-task document tasks does not trim the first tasks
         TaskRecord documentTask1 = createDocumentTask(".DocumentTask1",
                 FLAG_ACTIVITY_MULTIPLE_TASK);
@@ -252,6 +254,50 @@
     }
 
     @Test
+    public void testAddTasksMultipleTasks_expectRemovedNoTrim() throws Exception {
+        // Add multiple same-affinity non-document tasks, ensure that it removes the other task,
+        // but that it does not trim it
+        TaskRecord task1 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+                .build();
+        TaskRecord task2 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+                .build();
+        mRecentTasks.add(task1);
+        assertTrue(mCallbacksRecorder.added.size() == 1);
+        assertTrue(mCallbacksRecorder.added.contains(task1));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.isEmpty());
+        mCallbacksRecorder.clear();
+        mRecentTasks.add(task2);
+        assertTrue(mCallbacksRecorder.added.size() == 1);
+        assertTrue(mCallbacksRecorder.added.contains(task2));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.size() == 1);
+        assertTrue(mCallbacksRecorder.removed.contains(task1));
+    }
+
+    @Test
+    public void testAddTasksDifferentStacks_expectNoRemove() throws Exception {
+        // Adding the same task with different activity types should not trigger removal of the
+        // other task
+        TaskRecord task1 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+                .setStack(mHomeStack).build();
+        TaskRecord task2 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
+                .setStack(mStack).build();
+        mRecentTasks.add(task1);
+        mRecentTasks.add(task2);
+        assertTrue(mCallbacksRecorder.added.size() == 2);
+        assertTrue(mCallbacksRecorder.added.contains(task1));
+        assertTrue(mCallbacksRecorder.added.contains(task2));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.isEmpty());
+
+    }
+
+    @Test
     public void testUsersTasks() throws Exception {
         mRecentTasks.setOnlyTestVisibleRange();
 
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1211f00..2f2afd7 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -44,6 +44,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
 
 @SmallTest
 public class DisplayManagerServiceTest extends AndroidTestCase {
@@ -123,7 +124,7 @@
                 "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
                 uniqueId);
 
-        displayManager.performTraversalInTransactionFromWindowManagerInternal();
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
         // flush the handler
         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
@@ -161,7 +162,7 @@
                 "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
                 uniqueId);
 
-        displayManager.performTraversalInTransactionFromWindowManagerInternal();
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
 
         // flush the handler
         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index e40e3a4..e9289e5 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -42,11 +42,13 @@
 import android.security.keystore.KeyProperties;
 import android.security.keystore.recovery.KeyDerivationParams;
 import android.security.keystore.recovery.KeyChainSnapshot;
+import android.security.keystore.recovery.RecoveryController;
 import android.security.keystore.recovery.WrappedApplicationKey;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import android.util.Log;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
 
@@ -516,6 +518,34 @@
                 recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID2);
     }
 
+    @Test
+    public void run_customLockScreen_RecoveryStatusFailure() throws Exception {
+      mKeySyncTask = new KeySyncTask(
+          mRecoverableKeyStoreDb,
+          mRecoverySnapshotStorage,
+          mSnapshotListenersStorage,
+          TEST_USER_ID,
+          /*credentialType=*/ 3,
+          "12345",
+          /*credentialUpdated=*/ false,
+          mPlatformKeyManager);
+
+      addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
+      int status =
+          mRecoverableKeyStoreDb
+              .getStatusForAllKeys(TEST_RECOVERY_AGENT_UID)
+              .get(TEST_APP_KEY_ALIAS);
+      assertEquals(RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS, status);
+
+      mKeySyncTask.run();
+
+      status = mRecoverableKeyStoreDb
+          .getStatusForAllKeys(TEST_RECOVERY_AGENT_UID)
+          .get(TEST_APP_KEY_ALIAS);
+      assertEquals(RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE, status);
+    }
+
     private SecretKey addApplicationKey(int userId, int recoveryAgentUid, String alias)
             throws Exception{
         SecretKey applicationKey = generateKey();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index dfb2dbf..8b01d97 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -342,6 +342,30 @@
     }
 
     @Test
+    public void testInvalidateKeysForUserIdOnCustomScreenLock() {
+        int userId = 12;
+        int uid = 1009;
+        int generationId = 6;
+        int status = 120;
+        int status2 = 121;
+        String alias = "test";
+        byte[] nonce = getUtf8Bytes("nonce");
+        byte[] keyMaterial = getUtf8Bytes("keymaterial");
+        WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status);
+        mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey);
+
+        WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias);
+        assertThat(retrievedKey.getRecoveryStatus()).isEqualTo(status);
+
+        mRecoverableKeyStoreDb.setRecoveryStatus(uid, alias, status2);
+        mRecoverableKeyStoreDb.invalidateKeysForUserIdOnCustomScreenLock(userId);
+
+        retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias);
+        assertThat(retrievedKey.getRecoveryStatus())
+            .isEqualTo(RecoveryController.RECOVERY_STATUS_PERMANENT_FAILURE);
+    }
+
+    @Test
     public void setRecoveryServicePublicKey_replaceOldKey() throws Exception {
         int userId = 12;
         int uid = 10009;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 76e4e89..e0645b1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -20,11 +20,9 @@
 import org.junit.Test;
 
 import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.SecurityTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.WindowManager;
 
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -36,13 +34,12 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import java.util.function.Consumer;
+import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController;
 
 /**
  * Test class for {@link AppWindowContainerController}.
  *
- * Build/Install/Run:
- *  bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
+ * atest FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
  */
 @SmallTest
 @Presubmit
@@ -176,6 +173,33 @@
     }
 
     @Test
+    public void testTryTransferStartingWindowFromHiddenAboveToken() throws Exception {
+
+        // Add two tasks on top of each other.
+        TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(this);
+        final WindowTestUtils.TestAppWindowContainerController controllerTop =
+                createAppWindowController(taskController);
+        final WindowTestUtils.TestAppWindowContainerController controllerBottom =
+                createAppWindowController(taskController);
+
+        // Add a starting window.
+        controllerTop.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
+                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+                false, false);
+        waitUntilHandlersIdle();
+
+        // Make the top one invisible, and try transfering the starting window from the top to the
+        // bottom one.
+        controllerTop.setVisibility(false, false);
+        controllerBottom.mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+
+        // Assert that the bottom window now has the starting window.
+        assertNoStartingWindow(controllerTop.getAppWindowToken(mDisplayContent));
+        assertHasStartingWindow(controllerBottom.getAppWindowToken(mDisplayContent));
+    }
+
+    @Test
     public void testReparent() throws Exception {
         final StackWindowController stackController =
             createStackControllerOnDisplay(mDisplayContent);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 6784e30..6d9167f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -656,4 +656,8 @@
     @Override
     public void requestUserActivityNotification() {
     }
+
+    @Override
+    public void onLockTaskStateChangedLw(int lockTaskState) {
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index cdcb949..56b7d9f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -38,7 +38,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 
 import static org.junit.Assert.assertEquals;
@@ -288,6 +287,16 @@
         app.mToken.setHidden(false);
         app.mAttrs.alpha = 0.0f;
         assertFalse(app.canAffectSystemUiFlags());
+
+    }
+
+    @Test
+    public void testCanAffectSystemUiFlags_disallow() throws Exception {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        app.mToken.setHidden(false);
+        assertTrue(app.canAffectSystemUiFlags());
+        app.getTask().setCanAffectSystemUiFlags(false);
+        assertFalse(app.canAffectSystemUiFlags());
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 9008803..be58fd2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -160,6 +161,26 @@
     }
 
     @Test
+    public void testTotalSilence() {
+        mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+        mZenModeHelperSpy.applyRestrictions();
+
+        // Total silence will silence alarms, media and system noises (but not vibrations)
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+                AudioAttributes.USAGE_ALARM);
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+                AudioAttributes.USAGE_MEDIA);
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+                AudioAttributes.USAGE_GAME);
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+                AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+                AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
+        verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+                AudioAttributes.USAGE_UNKNOWN);
+    }
+
+    @Test
     public void testAlarmsOnly_alarmMediaMuteNotApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
@@ -179,9 +200,9 @@
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
                 AudioAttributes.USAGE_GAME);
 
-        // Alarms only will silence system noises
+        // Alarms only will silence system noises (but not vibrations)
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
-                AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
+                AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
                 AudioAttributes.USAGE_UNKNOWN);
     }
@@ -228,6 +249,7 @@
     @Test
     public void testZenAllCannotBypass() {
         // Only audio attributes with SUPPRESIBLE_NEVER can bypass
+        // with special case USAGE_ASSISTANCE_SONIFICATION
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
         mZenModeHelperSpy.mConfig.allowMedia = false;
@@ -247,9 +269,17 @@
         mZenModeHelperSpy.applyRestrictions();
 
         for (int usage : AudioAttributes.SDK_USAGES) {
-            boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
-                    != AudioAttributes.SUPPRESSIBLE_NEVER;
-            verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+            if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+                // only mute audio, not vibrations
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
+                        AppOpsManager.OP_PLAY_AUDIO);
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
+                        AppOpsManager.OP_VIBRATE);
+            } else {
+                boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
+                        != AudioAttributes.SUPPRESSIBLE_NEVER;
+                verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+            }
         }
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 1052e8f..3c4e333 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -1,7 +1,5 @@
 package com.android.server.slice;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -12,23 +10,18 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.slice.ISliceListener;
-import android.app.slice.Slice;
 import android.app.slice.SliceProvider;
 import android.app.slice.SliceSpec;
 import android.content.ContentProvider;
-import android.content.Context;
 import android.content.IContentProvider;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
@@ -83,7 +76,7 @@
         mIContentProvider = mock(IContentProvider.class);
         when(mContentProvider.getIContentProvider()).thenReturn(mIContentProvider);
         mContext.getContentResolver().addProvider(AUTH, mContentProvider);
-        mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI);
+        mPinnedSliceManager = new PinnedSliceState(mSliceService, TEST_URI, "pkg");
     }
 
     @Test
@@ -164,4 +157,4 @@
         verify(mSliceService).removePinnedSlice(eq(TEST_URI));
         assertFalse(mPinnedSliceManager.hasPinOrListener());
     }
-}
\ No newline at end of file
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index 6fc3009..4f446a9 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -18,6 +18,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -28,7 +29,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
-import android.app.slice.ISliceListener;
 import android.app.slice.SliceSpec;
 import android.content.pm.PackageManagerInternal;
 import android.net.Uri;
@@ -71,7 +71,7 @@
 
         mService = spy(new SliceManagerService(mContext, TestableLooper.get(this).getLooper()));
         mCreatedSliceState = mock(PinnedSliceState.class);
-        doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI));
+        doReturn(mCreatedSliceState).when(mService).createPinnedSlice(eq(TEST_URI), anyString());
     }
 
     @After
@@ -85,7 +85,7 @@
 
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
-        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI));
+        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), eq("pkg"));
     }
 
     @Test
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
new file mode 100644
index 0000000..5d2c225
--- /dev/null
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -0,0 +1,167 @@
+package android.telephony;
+
+import static android.telephony.ServiceState.DUPLEX_MODE_FDD;
+import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
+import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
+
+import android.telephony.AccessNetworkConstants.EutranBand;
+import android.telephony.ServiceState.DuplexMode;
+
+
+/**
+ * Utilities to map between radio constants.
+ *
+ * @hide
+ */
+public class AccessNetworkUtils {
+
+    // do not instantiate
+    private AccessNetworkUtils() {}
+
+    public static final int INVALID_BAND = -1;
+
+    /**
+     * Gets the duplex mode for the given EUTRAN operating band.
+     *
+     * <p>See 3GPP 36.101 sec 5.5-1 for calculation
+     *
+     * @param band The EUTRAN band number
+     * @return The duplex mode of the given EUTRAN band
+     */
+    @DuplexMode
+    public static int getDuplexModeForEutranBand(int band) {
+        if (band == INVALID_BAND) {
+            return DUPLEX_MODE_UNKNOWN;
+        }
+
+        if (band >= EutranBand.BAND_68) {
+            return DUPLEX_MODE_UNKNOWN;
+        } else if (band >= EutranBand.BAND_65) {
+            return DUPLEX_MODE_FDD;
+        } else if (band >= EutranBand.BAND_47) {
+            return DUPLEX_MODE_UNKNOWN;
+        } else if (band >= EutranBand.BAND_33) {
+            return DUPLEX_MODE_TDD;
+        } else if (band >= EutranBand.BAND_1) {
+            return DUPLEX_MODE_FDD;
+        }
+
+        return DUPLEX_MODE_UNKNOWN;
+    }
+
+    /**
+     * Gets the EUTRAN Operating band for a given downlink EARFCN.
+     *
+     * <p>See 3GPP 36.101 sec 5.7.3-1 for calculation.
+     *
+     * @param earfcn The downlink EARFCN
+     * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
+     */
+    public static int getOperatingBandForEarfcn(int earfcn) {
+        if (earfcn > 67535) {
+            return INVALID_BAND;
+        } else if (earfcn >= 67366) {
+            return INVALID_BAND; // band 67 only for CarrierAgg
+        } else if (earfcn >= 66436) {
+            return EutranBand.BAND_66;
+        } else if (earfcn >= 65536) {
+            return EutranBand.BAND_65;
+        } else if (earfcn > 54339) {
+            return INVALID_BAND;
+        } else if (earfcn >= 46790 /* inferred from the end range of BAND_45 */) {
+            return EutranBand.BAND_46;
+        } else if (earfcn >= 46590) {
+            return EutranBand.BAND_45;
+        } else if (earfcn >= 45590) {
+            return EutranBand.BAND_44;
+        } else if (earfcn >= 43590) {
+            return EutranBand.BAND_43;
+        } else if (earfcn >= 41590) {
+            return EutranBand.BAND_42;
+        } else if (earfcn >= 39650) {
+            return EutranBand.BAND_41;
+        } else if (earfcn >= 38650) {
+            return EutranBand.BAND_40;
+        } else if (earfcn >= 38250) {
+            return EutranBand.BAND_39;
+        } else if (earfcn >= 37750) {
+            return EutranBand.BAND_38;
+        } else if (earfcn >= 37550) {
+            return EutranBand.BAND_37;
+        } else if (earfcn >= 36950) {
+            return EutranBand.BAND_36;
+        } else if (earfcn >= 36350) {
+            return EutranBand.BAND_35;
+        } else if (earfcn >= 36200) {
+            return EutranBand.BAND_34;
+        } else if (earfcn >= 36000) {
+            return EutranBand.BAND_33;
+        } else if (earfcn > 10359) {
+            return INVALID_BAND;
+        } else if (earfcn >= 9920) {
+            return INVALID_BAND; // band 32 only for CarrierAgg
+        } else if (earfcn >= 9870) {
+            return EutranBand.BAND_31;
+        } else if (earfcn >= 9770) {
+            return EutranBand.BAND_30;
+        } else if (earfcn >= 9660) {
+            return INVALID_BAND; // band 29 only for CarrierAgg
+        } else if (earfcn >= 9210) {
+            return EutranBand.BAND_28;
+        } else if (earfcn >= 9040) {
+            return EutranBand.BAND_27;
+        } else if (earfcn >= 8690) {
+            return EutranBand.BAND_26;
+        } else if (earfcn >= 8040) {
+            return EutranBand.BAND_25;
+        } else if (earfcn >= 7700) {
+            return EutranBand.BAND_24;
+        } else if (earfcn >= 7500) {
+            return EutranBand.BAND_23;
+        } else if (earfcn >= 6600) {
+            return EutranBand.BAND_22;
+        } else if (earfcn >= 6450) {
+            return EutranBand.BAND_21;
+        } else if (earfcn >= 6150) {
+            return EutranBand.BAND_20;
+        } else if (earfcn >= 6000) {
+            return EutranBand.BAND_19;
+        } else if (earfcn >= 5850) {
+            return EutranBand.BAND_18;
+        } else if (earfcn >= 5730) {
+            return EutranBand.BAND_17;
+        } else if (earfcn > 5379) {
+            return INVALID_BAND;
+        } else if (earfcn >= 5280) {
+            return EutranBand.BAND_14;
+        } else if (earfcn >= 5180) {
+            return EutranBand.BAND_13;
+        } else if (earfcn >= 5010) {
+            return EutranBand.BAND_12;
+        } else if (earfcn >= 4750) {
+            return EutranBand.BAND_11;
+        } else if (earfcn >= 4150) {
+            return EutranBand.BAND_10;
+        } else if (earfcn >= 3800) {
+            return EutranBand.BAND_9;
+        } else if (earfcn >= 3450) {
+            return EutranBand.BAND_8;
+        } else if (earfcn >= 2750) {
+            return EutranBand.BAND_7;
+        } else if (earfcn >= 2650) {
+            return EutranBand.BAND_6;
+        } else if (earfcn >= 2400) {
+            return EutranBand.BAND_5;
+        } else if (earfcn >= 1950) {
+            return EutranBand.BAND_4;
+        } else if (earfcn >= 1200) {
+            return EutranBand.BAND_3;
+        } else if (earfcn >= 600) {
+            return EutranBand.BAND_2;
+        } else if (earfcn >= 0) {
+            return EutranBand.BAND_1;
+        }
+
+        return INVALID_BAND;
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index e092d52..08f8bb6 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -68,6 +68,9 @@
      */
     public static final int TYPE_TDSCDMA        = 5;
 
+    /** @hide */
+    public static final int INVALID_CHANNEL_NUMBER = -1;
+
     // Log tag
     /** @hide */
     protected final String mTag;
@@ -125,6 +128,16 @@
     public @Type int getType() { return mType; }
 
     /**
+     * Returns the channel number of the cell identity.
+     *
+     * @hide
+     * @return The channel number, or {@link #INVALID_CHANNEL_NUMBER} if not implemented
+     */
+    public int getChannelNumber() {
+        return INVALID_CHANNEL_NUMBER;
+    }
+
+    /**
      * Used by child classes for parceling.
      *
      * @hide
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index d35eb60..52944a8 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -203,6 +203,11 @@
         return mAlphaShort;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mArfcn;
+    }
 
     /**
      * @deprecated Primary Scrambling Code is not applicable to GSM.
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 2b8eb5f..37fb075 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -213,6 +213,12 @@
         return mAlphaShort;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mEarfcn;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mMccStr, mMncStr, mCi, mPci, mTac, mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index a5fd7dd..affa0c1 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -206,6 +206,12 @@
         return mUarfcn;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mUarfcn;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index ce1b80c..81a966b 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -131,6 +131,14 @@
      */
     public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
 
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {RESULT_SUCCESSFUL, RESULT_CANCELLED, RESULT_EXPIRED, RESULT_IO_ERROR,
+            RESULT_SERVICE_ID_NOT_DEFINED, RESULT_DOWNLOAD_FAILURE, RESULT_OUT_OF_STORAGE,
+            RESULT_FILE_ROOT_UNREACHABLE}, prefix = { "RESULT_" })
+    public @interface DownloadResultCode{}
+
     /**
      * Indicates that the download was successful.
      */
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 7f43ee5..073c313 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -115,6 +115,8 @@
             telephony.stopNetworkScan(mSubId, mScanId);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "stopNetworkScan  RemoteException", ex);
+        } catch (RuntimeException ex) {
+            Rlog.e(TAG, "stopNetworkScan  RuntimeException", ex);
         }
     }
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 82a7450..a9c1cf6 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -471,9 +471,13 @@
      */
     @DuplexMode
     public int getDuplexMode() {
-        // TODO(b/72117602) determine duplex mode from channel number, using 3GPP 36.101 sections
-        // 5.7.3-1 and 5.5-1
-        return DUPLEX_MODE_UNKNOWN;
+        // only support LTE duplex mode
+        if (!isLte(mRilDataRadioTechnology)) {
+            return DUPLEX_MODE_UNKNOWN;
+        }
+
+        int band = AccessNetworkUtils.getOperatingBandForEarfcn(mChannelNumber);
+        return AccessNetworkUtils.getDuplexModeForEutranBand(band);
     }
 
     /**
@@ -891,6 +895,7 @@
             .append(", mDataRegState=").append(mDataRegState)
             .append("(" + rilServiceStateToString(mDataRegState) + ")")
             .append(", mChannelNumber=").append(mChannelNumber)
+            .append(", duplexMode()=").append(getDuplexMode())
             .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
             .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
             .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 22795b1..7add893 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5351,6 +5351,23 @@
     }
 
     /**
+     * @return true if the IMS resolver is busy resolving a binding and should not be considered
+     * available, false if the IMS resolver is idle.
+     * @hide
+     */
+    public boolean isResolvingImsBinding() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.isResolvingImsBinding();
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
+        }
+        return false;
+    }
+
+    /**
      * Set IMS registration state
      *
      * @param Registration state
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 946cecf..99e2db8 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -145,7 +145,8 @@
                         break;
                     case CALLBACK_SCAN_ERROR:
                         try {
-                            executor.execute(() -> callback.onError(message.arg1));
+                            final int errorCode = message.arg1;
+                            executor.execute(() -> callback.onError(errorCode));
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onError", e);
                         }
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 0c17147..125161d 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -60,6 +60,7 @@
     private final String mCardId;
     private final @CardStateInfo int mCardStateInfo;
     private final int mLogicalSlotIdx;
+    private final boolean mIsExtendedApduSupported;
 
     public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
         @Override
@@ -79,6 +80,7 @@
         mCardId = in.readString();
         mCardStateInfo = in.readInt();
         mLogicalSlotIdx = in.readInt();
+        mIsExtendedApduSupported = in.readByte() != 0;
     }
 
     @Override
@@ -88,6 +90,7 @@
         dest.writeString(mCardId);
         dest.writeInt(mCardStateInfo);
         dest.writeInt(mLogicalSlotIdx);
+        dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
     }
 
     @Override
@@ -96,12 +99,13 @@
     }
 
     public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
-            @CardStateInfo int cardStateInfo, int logicalSlotIdx) {
+            @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported) {
         this.mIsActive = isActive;
         this.mIsEuicc = isEuicc;
         this.mCardId = cardId;
         this.mCardStateInfo = cardStateInfo;
         this.mLogicalSlotIdx = logicalSlotIdx;
+        this.mIsExtendedApduSupported = isExtendedApduSupported;
     }
 
     public boolean getIsActive() {
@@ -125,6 +129,13 @@
         return mLogicalSlotIdx;
     }
 
+    /**
+     * @return {@code true} if this slot supports extended APDU from ATR, {@code false} otherwise.
+     */
+    public boolean getIsExtendedApduSupported() {
+        return mIsExtendedApduSupported;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
@@ -139,7 +150,8 @@
                 && (mIsEuicc == that.mIsEuicc)
                 && (mCardId == that.mCardId)
                 && (mCardStateInfo == that.mCardStateInfo)
-                && (mLogicalSlotIdx == that.mLogicalSlotIdx);
+                && (mLogicalSlotIdx == that.mLogicalSlotIdx)
+                && (mIsExtendedApduSupported == that.mIsExtendedApduSupported);
     }
 
     @Override
@@ -150,6 +162,7 @@
         result = 31 * result + Objects.hashCode(mCardId);
         result = 31 * result + mCardStateInfo;
         result = 31 * result + mLogicalSlotIdx;
+        result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
         return result;
     }
 
@@ -165,6 +178,8 @@
                 + mCardStateInfo
                 + ", phoneId="
                 + mLogicalSlotIdx
+                + ", mIsExtendedApduSupported="
+                + mIsExtendedApduSupported
                 + ")";
     }
 }
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 2748cb5..c008711 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -161,11 +161,6 @@
         }
 
         @Override
-        public void notifyImsFeatureReady(int slotId, int featureType) {
-            ImsService.this.notifyImsFeatureReady(slotId, featureType);
-        }
-
-        @Override
         public IImsConfig getConfig(int slotId) {
             ImsConfigImplBase c = ImsService.this.getConfig(slotId);
             return c != null ? c.getIImsConfig() : null;
@@ -274,25 +269,6 @@
         }
     }
 
-    private void notifyImsFeatureReady(int slotId, int featureType) {
-        synchronized (mFeaturesBySlot) {
-            // get ImsFeature associated with the slot/feature
-            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
-            if (features == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
-                        "slot " + slotId);
-                return;
-            }
-            ImsFeature f = features.get(featureType);
-            if (f == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
-                        + featureType + " exists on slot " + slotId);
-                return;
-            }
-            f.onFeatureReady();
-        }
-    }
-
     /**
      * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
      * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 86f8606..c7da681 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -36,8 +36,6 @@
     ImsFeatureConfiguration querySupportedImsFeatures();
     // Synchronous call to ensure the ImsService is ready before continuing with feature creation.
     void notifyImsServiceReadyForFeatureCreation();
-    // Synchronous call to ensure the new ImsFeature is ready before using the Feature.
-    void notifyImsFeatureReady(int slotId, int featureType);
     void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
     IImsConfig getConfig(int slotId);
     IImsRegistration getRegistration(int slotId);
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 2fffd36..c073d1a 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -575,7 +575,7 @@
      */
     public ImsUtImplBase getUt() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsUtImplBase();
     }
 
     /**
@@ -584,7 +584,7 @@
      */
     public ImsEcbmImplBase getEcbm() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsEcbmImplBase();
     }
 
     /**
@@ -593,7 +593,7 @@
      */
     public ImsMultiEndpointImplBase getMultiEndpoint() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsMultiEndpointImplBase();
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 98b67c3..2f52c0a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -21,6 +21,7 @@
 import android.os.Parcelable;
 import android.telephony.ims.feature.ImsFeature;
 import android.util.ArraySet;
+import android.util.Pair;
 
 import java.util.Set;
 
@@ -34,14 +35,57 @@
  */
 @SystemApi
 public final class ImsFeatureConfiguration implements Parcelable {
+
+    public static final class FeatureSlotPair {
+        /**
+         * SIM slot that this feature is associated with.
+         */
+        public final int slotId;
+        /**
+         * The feature that this slotId supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
+         */
+        public final @ImsFeature.FeatureType int featureType;
+
+        /**
+         * A mapping from slotId to IMS Feature type.
+         * @param slotId the SIM slot ID associated with this feature.
+         * @param featureType The feature that this slotId supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
+         */
+        public FeatureSlotPair(int slotId, @ImsFeature.FeatureType int featureType) {
+            this.slotId = slotId;
+            this.featureType = featureType;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            FeatureSlotPair that = (FeatureSlotPair) o;
+
+            if (slotId != that.slotId) return false;
+            return featureType == that.featureType;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = slotId;
+            result = 31 * result + featureType;
+            return result;
+        }
+    }
+
     /**
      * Features that this ImsService supports.
      */
-    private final Set<Integer> mFeatures;
+    private final Set<FeatureSlotPair> mFeatures;
 
     /**
-     * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
-     * easier.
+     * Builder for {@link ImsFeatureConfiguration}.
      */
     public static class Builder {
             ImsFeatureConfiguration mConfig;
@@ -50,12 +94,15 @@
         }
 
         /**
-         * @param feature A feature defined in {@link ImsFeature.FeatureType} that this service
-         *         supports.
+         * Adds an IMS feature associated with a SIM slot ID.
+         * @param slotId The slot ID associated with the IMS feature.
+         * @param featureType The feature that the slot ID supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
          * @return a {@link Builder} to continue constructing the ImsFeatureConfiguration.
          */
-        public Builder addFeature(@ImsFeature.FeatureType int feature) {
-            mConfig.addFeature(feature);
+        public Builder addFeature(int slotId, @ImsFeature.FeatureType int featureType) {
+            mConfig.addFeature(slotId, featureType);
             return this;
         }
 
@@ -66,8 +113,7 @@
 
     /**
      * Creates with all registration features empty.
-     *
-     * Consider using the provided {@link Builder} to create this configuration instead.
+     * @hide
      */
     public ImsFeatureConfiguration() {
         mFeatures = new ArraySet<>();
@@ -76,45 +122,41 @@
     /**
      * Configuration of the ImsService, which describes which features the ImsService supports
      * (for registration).
-     * @param features an array of feature integers defined in {@link ImsFeature} that describe
-     * which features this ImsService supports. Supported values are
-     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
-     * {@link ImsFeature#FEATURE_RCS}.
+     * @param features a set of {@link FeatureSlotPair}s that describe which features this
+     *         ImsService supports.
      * @hide
      */
-    public ImsFeatureConfiguration(int[] features) {
+    public ImsFeatureConfiguration(Set<FeatureSlotPair> features) {
         mFeatures = new ArraySet<>();
 
         if (features != null) {
-            for (int i : features) {
-                mFeatures.add(i);
-            }
+            mFeatures.addAll(features);
         }
     }
 
     /**
-     * @return an int[] containing the features that this ImsService supports. Supported values are
-     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
-     * {@link ImsFeature#FEATURE_RCS}.
+     * @return a set of supported slot ID to feature type pairs contained within a
+     * {@link FeatureSlotPair}.
      */
-    public int[] getServiceFeatures() {
-        return mFeatures.stream().mapToInt(i->i).toArray();
+    public Set<FeatureSlotPair> getServiceFeatures() {
+        return new ArraySet<>(mFeatures);
     }
 
-    void addFeature(int feature) {
-        mFeatures.add(feature);
+    /**
+     * @hide
+     */
+    void addFeature(int slotId, int feature) {
+        mFeatures.add(new FeatureSlotPair(slotId, feature));
     }
 
     /** @hide */
     protected ImsFeatureConfiguration(Parcel in) {
-        int[] features = in.createIntArray();
-        if (features != null) {
-            mFeatures = new ArraySet<>(features.length);
-            for(Integer i : features) {
-                mFeatures.add(i);
-            }
-        } else {
-            mFeatures = new ArraySet<>();
+        int featurePairLength = in.readInt();
+        // length
+        mFeatures = new ArraySet<>(featurePairLength);
+        for (int i = 0; i < featurePairLength; i++) {
+            // pair of reads for each entry (slotId->featureType)
+            mFeatures.add(new FeatureSlotPair(in.readInt(), in.readInt()));
         }
     }
 
@@ -138,7 +180,15 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
+        FeatureSlotPair[] featureSlotPairs = new FeatureSlotPair[mFeatures.size()];
+        mFeatures.toArray(featureSlotPairs);
+        // length of list
+        dest.writeInt(featureSlotPairs.length);
+        // then pairs of integers for each entry (slotId->featureType).
+        for (FeatureSlotPair featureSlotPair : featureSlotPairs) {
+            dest.writeInt(featureSlotPair.slotId);
+            dest.writeInt(featureSlotPair.featureType);
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4002d3c..afbb947 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -829,6 +829,12 @@
     boolean isEmergencyMmTelAvailable(int slotId);
 
     /**
+     * @return true if the IMS resolver is busy resolving a binding and should not be considered
+     * available, false if the IMS resolver is idle.
+     */
+    boolean isResolvingImsBinding();
+
+    /**
      * Set the network selection mode to automatic.
      *
      * @param subId the id of the subscription to update.
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a3a3080..ee7084a 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -25,6 +25,7 @@
  */
 
 import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
 
 /**
  * {@hide}
@@ -162,8 +163,8 @@
     int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA   = 20; /* TD-SCDMA, GSM/WCDMA and LTE */
     int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA  = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/
     int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */
-    int PREFERRED_NETWORK_MODE      = SystemProperties.getInt("ro.telephony.default_network",
-            NETWORK_MODE_WCDMA_PREF);
+    int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0,
+            "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF)));
 
     int BAND_MODE_UNSPECIFIED = 0;      //"unspecified" (selected by baseband automatically)
     int BAND_MODE_EURO = 1;             //"EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 93fa598..6865f77 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -86,9 +86,6 @@
         /** WPA is not used; plaintext or static WEP could be used. */
         public static final int NONE = 0;
         /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
-        /** @deprecated Due to security and performance limitations, use of WPA-1 networks
-         * is discouraged. WPA-2 (RSN) should be used instead. */
-        @Deprecated
         public static final int WPA_PSK = 1;
         /** WPA using EAP authentication. Generally used with an external authentication server. */
         public static final int WPA_EAP = 2;
@@ -122,7 +119,7 @@
 
         public static final String varName = "key_mgmt";
 
-        public static final String[] strings = { "NONE", /* deprecated */ "WPA_PSK", "WPA_EAP",
+        public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
                 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
     }
 
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index eca8406..ebf6007 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -133,7 +133,8 @@
      *                    match filter. For {@link PublishConfig#PUBLISH_TYPE_SOLICITED},
      *                    {@link SubscribeConfig#SUBSCRIBE_TYPE_ACTIVE} discovery sessions this
      *                    is the subscriber's match filter.
-     * @param distanceMm The measured distance to the Publisher in mm.
+     * @param distanceMm The measured distance to the Publisher in mm. Note: the measured distance
+     *                   may be negative for very close devices.
      */
     public void onServiceDiscoveredWithinRange(PeerHandle peerHandle,
         byte[] serviceSpecificInfo, List<byte[]> matchFilter, int distanceMm) {
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 2ec3b70..51353c6 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -418,8 +418,8 @@
          * notification. I.e. discovery will be triggered if we've found a matching publisher
          * (based on the other criteria in this configuration) <b>and</b> the distance to the
          * publisher is larger than the value specified in this API. Can be used in conjunction with
-         * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min <
-         * distance < max.
+         * {@link #setMaxDistanceMm(int)} to specify a geofence, i.e. discovery with min <=
+         * distance <= max.
          * <p>
          * For ranging to be used in discovery it must also be enabled on the publisher using
          * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may
@@ -453,8 +453,8 @@
          * notification. I.e. discovery will be triggered if we've found a matching publisher
          * (based on the other criteria in this configuration) <b>and</b> the distance to the
          * publisher is smaller than the value specified in this API. Can be used in conjunction
-         * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min <
-         * distance < max.
+         * with {@link #setMinDistanceMm(int)} to specify a geofence, i.e. discovery with min <=
+         * distance <= max.
          * <p>
          * For ranging to be used in discovery it must also be enabled on the publisher using
          * {@link PublishConfig.Builder#setRangingEnabled(boolean)}. However, ranging may
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 936a1f2..7fe85be 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -147,6 +147,8 @@
      * @return The distance (in mm) to the device specified by {@link #getMacAddress()} or
      * {@link #getPeerHandle()}.
      * <p>
+     * Note: the measured distance may be negative for very close devices.
+     * <p>
      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
      * exception.
      */
@@ -189,7 +191,8 @@
     }
 
     /**
-     * @return The Location Configuration Information (LCI) as self-reported by the peer.
+     * @return The Location Configuration Information (LCI) as self-reported by the peer. The format
+     * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.10.
      * <p>
      * Note: the information is NOT validated - use with caution. Consider validating it with
      * other sources of information before using it.
@@ -207,7 +210,8 @@
     }
 
     /**
-     * @return The Location Civic report (LCR) as self-reported by the peer.
+     * @return The Location Civic report (LCR) as self-reported by the peer. The format
+     * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
      * <p>
      * Note: the information is NOT validated - use with caution. Consider validating it with
      * other sources of information before using it.